python: можно ли подключить консоль к запущенному процессу


Я просто хочу увидеть состояние процесса, можно ли подключить консоль в процесс, чтобы я мог вызывать функции внутри процесса и видеть некоторые глобальные переменные.

лучше процесс работает без ущерба (конечно, производительность может немного снизиться)

6 73

6 ответов:

Если у вас есть доступ к исходному коду программы, вы можете добавить эту функциональность относительно легко.

посмотреть рецепт 576515:Debugging a running python process by interrupting and providing an interactive prompt (Python)

цитата:

Это обеспечивает код, чтобы позволить любой python программа, которая использует его, чтобы быть прервано в текущей точке, и общался с помощью обычного python интерактивная консоль. Это позволяет локальные, глобальные и связанные с ними программы государство, подлежащее расследованию, а также вызов произвольных функций и занятия.

использовать, процесс должен импортировать модуль и вызов listen() в любой момент во время запуска. Чтобы прервать это процесс, скрипт можно запустить непосредственно, давая идентификатор процесса процесс отладки в качестве параметра.


другая реализация примерно той же концепции обеспечивается rconsole. Из документации:

rconsole дистанционное Консоль Python с автоматическим завершением, которое может быть используется для проверки и изменения пространство имен скрипта.

чтобы вызвать в скрипте do:

from rfoo.utils import rconsole
rconsole.spawn_server()

чтобы прикрепить из оболочки делают:

$ rconsole

примечание по безопасности: слушатель rconsole начато с spawn_server () будет примите любое локальное соединение и может поэтому небезопасно использовать в общем доступе хостинг или аналогичные среды!

это прервет ваш процесс (если вы не запустите его в потоке), но вы можете использовать code модуль для запуска консоли Python:

import code
code.interact()

это будет блокироваться до тех пор, пока пользователь не выйдет из интерактивной консоли, выполнив exit().

The code модуль доступен в, по крайней мере, в Python версии 2.6, наверное, другим.

я склонен использовать этот подход в сочетании с сигналами для моей работы в Linux (для Windows, см. ниже). Я хлопаю это в верхней части моего Скрипты Python:

import code
import signal
signal.signal(signal.SIGUSR2, lambda sig, frame: code.interact())

а затем вызвать его из оболочки с kill -SIGUSR2 <PID>, где <PID> - это идентификатор процесса. Затем процесс останавливает все, что он делает, и представляет консоль:

Python 2.6.2 (r262:71600, Oct  9 2009, 17:53:52)
[GCC 3.4.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

обычно оттуда я загружаю серверный компонент удаленного отладчика, как отличный WinPDB.

Windows не является POSIX-совместимая ОС, и поэтому не обеспечивает те же сигналы, что и Linux. Однако,Python v2. 2 и выше выставляют специфичный для Windows сигнал SIGBREAK (запускается клавишей CTRL+Pause/Break). Это делает не мешают нормально CTRL+C (SIGINT) деятельность, и так сподручная альтернатива.

поэтому портативный, но немного уродливый, версия выше:

import code
import signal
signal.signal(
        vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"),
        lambda sig, frame: code.interact()
        )

преимущества такого подхода:

  • нет внешних модулей (все стандартные Python вещи)
  • почти не потребляет ресурсы до срабатывания (2x импорт)

вот код, который я использую в своей рабочей среде, который загрузит серверную часть WinPDB (если она доступна) и вернется к открытию консоли Python.

# Break into a Python console upon SIGUSR1 (Linux) or SIGBREAK (Windows:
# CTRL+Pause/Break).  To be included in all production code, just in case.
def debug_signal_handler(signal, frame):
    del signal
    del frame

    try:
        import rpdb2
        print
        print
        print "Starting embedded RPDB2 debugger. Password is 'foobar'"
        print
        print
        rpdb2.start_embedded_debugger("foobar", True, True)
        rpdb2.setbreak(depth=1)
        return
    except StandardError:
        pass

    try:
        import code
        code.interact()
    except StandardError as ex:
        print "%r, returning to normal program flow" % ex

import signal
try:
    signal.signal(
            vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR1"),
            debug_signal_handler
            )
except ValueError:
    # Typically: ValueError: signal only works in main thread
    pass

использовать пиразит-оболочка. Я не могу поверить, что это работает так хорошо, но это так. "дайте ему пид, получите оболочку".

$ sudo pip install pyrasite
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope # If YAMA activated, see below.
$ pyrasite-shell 16262
Pyrasite Shell 2.0
Connected to 'python my_script.py'
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.

>>> globals()
>>> print(db_session)
>>> run_some_local_function()
>>> some_existing_local_variable = 'new value'

это запускает оболочку python с доступом к переменным globals() и locals() этого запущенного процесса python и другим замечательным вещам.

только тестировал это лично на Ubuntu, но, похоже, тоже обслуживает OSX.

адаптировано из ответ.

Примечание: переключение линии прочь ptrace_scope свойство необходимо только для ядер / систем, которые были построены с CONFIG_SECURITY_YAMA далее. Будьте осторожны, возясь с ptrace_scope в чувствительных средах, потому что это может привести к определенным уязвимостям безопасности. Смотрите здесь для сведения.

почему бы просто не использовать pdb модуль? Он позволяет остановить скрипт, проверить значения элементов и выполнить код строка за строкой. И поскольку он построен на интерпретаторе Python, он также предоставляет функции, предоставляемые классическим интерпретатором. Чтобы использовать его, просто поместите эти 2 строки в свой код, где вы хотите остановиться и проверить его:

import pdb
pdb.set_trace()

другая возможность, без добавления материала в Скрипты python, описана здесь:

https://wiki.python.org/moin/DebuggingWithGdb

к сожалению, это решение также требует некоторой предусмотрительности, по крайней мере, в той степени, в которой вам нужно использовать версию python с отладочными символами в ней.

используя PyCharm, я получал сбой подключения к процессу в Ubuntu. Исправление для этого-отключить YAMA. Для получения дополнительной информации см. askubuntu

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope