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

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

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

Ответы

Ответ 1

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

См. Рецепт 576515: Debugging a running python process by interrupting and providing an interactive prompt (Python)

Цитата:

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

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


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

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

Чтобы вызвать в script do:

from rfoo.utils import rconsole
rconsole.spawn_server()

Чтобы установить из оболочки, выполните:

$ rconsole

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

Ответ 2

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

import code
code.interact()

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

Модуль code доступен, по крайней мере, для Python v2.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

Ответ 3

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

$ 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 в чувствительных средах, потому что это может привести к определенным уязвимостям безопасности. Подробнее см. Здесь.

Ответ 4

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

import pdb
pdb.set_trace()

Ответ 5

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

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

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

Ответ 6

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

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