Я просто хочу побачити стан процесу, чи можна приєднати до нього консоль, щоб я міг викликати функції всередині процесу і побачити деякі глобальні змінні.
Краще, щоб процес працював без впливу (звичайно, продуктивність може трохи знизитися)
Я просто хочу побачити стан процесу, чи можна приєднати до нього консоль, щоб я міг викликати функції всередині процесу і побачити деякі глобальні змінні.
Краще, щоб процес працював без впливу (звичайно, продуктивність може трохи знизитися)
Відповіді:
Якщо у вас є доступ до вихідного коду програми, ви можете порівняно легко додати цю функціональність.
Див. Рецепт 576515 :Debugging a running python process by interrupting and providing an interactive prompt (Python)
Цитувати:
Це забезпечує код, який дозволяє будь-якій програмі python, яка використовує його, перериватися в поточній точці та обмінюватися даними через звичайну інтерактивну консоль python. Це дозволяє досліджувати місцеві жителі, глобальні регіони та пов'язаний стан програм, а також викликати довільні функції та класи.
Для використання процес повинен імпортувати модуль і викликати Listen () у будь-який момент під час запуску. Щоб перервати цей процес, скрипт можна запустити безпосередньо, даючи ідентифікатор процесу для налагодження як параметр.
Інша реалізація приблизно тієї ж концепції представлена rconsole . З документації:
rconsole - це віддалена консоль Python з автоматичним заповненням, яку можна використовувати для перевірки та модифікації простору імен запущеного сценарію.
Щоб викликати сценарій, виконайте:
from rfoo.utils import rconsole
rconsole.spawn_server()
Щоб прикріпити з оболонки:
$ rconsole
Примітка щодо безпеки: Слухач rconsole, запущений із spawn_server (), прийме будь-яке локальне підключення і, отже, може бути небезпечним для використання в спільному хостингу або подібних середовищах!
rfoo._rfoo.EofError: 0
Це перерве ваш процес (якщо ви не запустите його в потоці), але ви можете використовувати 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()
)
Переваги такого підходу:
Ось код, який я використовую у своєму виробничому середовищі, який завантажує серверну сторону 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
Використовуйте піразитову оболонку . Я не можу повірити, що це працює так добре, але це робить. Msgstr " Дайте йому під, отримайте оболонку ".
$ 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 () та local () цього запущеного процесу python та інших чудових речей.
Лише тестував це особисто на Ubuntu, але, схоже, це також стосується OSX.
Адаптовано з цієї відповіді .
Примітка: Вимкнення ptrace_scopeвластивості рядка необхідно лише для ядер / систем, які були побудовані з CONFIG_SECURITY_YAMAon. Будьте обережні, возитися з ptrace_scope в чутливих середовищах, оскільки це може спричинити певні уразливості безпеки. Детальніше див. Тут .
Чому б не просто використовувати модуль pdb ? Це дозволяє зупинити сценарій, перевірити значення елементів і виконати код за рядком. Оскільки він побудований на інтерпретаторі Python, він також надає функції класичного інтерпретатора. Щоб використовувати його, просто вставте ці 2 рядки у свій код, де ви хочете зупинитись та перевірити його:
import pdb
pdb.set_trace()
Інша можливість, без додавання матеріалів до скриптів python, описана тут:
https://wiki.python.org/moin/DebuggingWithGdb
На жаль, це рішення також вимагає певної продуманості, принаймні настільки, наскільки вам потрібно використовувати версію python із символами налагодження.