python: czy można podłączyć konsolę do działającego procesu
81
Chcę tylko zobaczyć stan procesu, czy można dołączyć konsolę do procesu, abym mógł wywoływać funkcje wewnątrz procesu i zobaczyć niektóre zmienne globalne.
Lepiej, aby proces przebiegał bez wpływu (oczywiście wydajność może nieco spaść)
Jeśli masz dostęp do kodu źródłowego programu, możesz stosunkowo łatwo dodać tę funkcjonalność.
Patrz przepis 576515 :Debugging a running python process by interrupting and providing an interactive prompt (Python)
Cytować:
Zapewnia to kod umożliwiający przerwanie dowolnego programu w Pythonie, który go używa, w bieżącym momencie i komunikowanie się z nim za pośrednictwem zwykłej interaktywnej konsoli Pythona. Pozwala to na badanie lokalnych, globalnych i powiązanych stanów programu, a także wywoływanie dowolnych funkcji i klas.
Aby go użyć, proces powinien zaimportować moduł i wywołać funkcję Listen () w dowolnym momencie podczas uruchamiania. Aby przerwać ten proces, skrypt można uruchomić bezpośrednio, podając jako parametr identyfikator procesu do debugowania.
Kolejną implementację mniej więcej tej samej koncepcji zapewnia rconsole . Z dokumentacji:
rconsole to zdalna konsola Pythona z funkcją automatycznego uzupełniania, której można używać do sprawdzania i modyfikowania przestrzeni nazw uruchomionego skryptu.
Aby wywołać w skrypcie, wykonaj:
from rfoo.utils import rconsole
rconsole.spawn_server()
Aby dołączyć z muszli, wykonaj:
$ rconsole
Uwaga dotycząca bezpieczeństwa: odbiornik rconsole uruchomiony za pomocą spawn_server () akceptuje każde połączenie lokalne i dlatego może być niebezpieczny w użyciu we współdzielonym hostingu lub podobnych środowiskach!
To naprawdę bardzo fajny przepis. Używanie potoków i plików do wejścia i wyjścia jest naprawdę sprytne i myślę, że każdy przyzwoity projekt skorzystałby na takiej funkcjonalności.
erkmene
2
Jest to jednak bardzo niebezpieczne, więc używaj ostrożnie
fmark
Wypróbowałem przepis i zepsuło to moją instalację Pythona. Obiekt „moduł” nie ma atrybutu „getmro”
Victor „Chris” Cabral
Skompilowałem rozszerzenie cython, po dodaniu kodu do kodu i uruchomiłem serwer rpc, ale rconsole zawsze zepsuje haniebnie po każdej operacji. rfoo._rfoo.EofError: 0
Sajuuk,
60
Spowoduje to przerwanie procesu (chyba że uruchomisz go w wątku), ale możesz użyć codemodułu do uruchomienia konsoli Pythona:
import code
code.interact()
Będzie to blokowane, dopóki użytkownik nie wyjdzie z konsoli interaktywnej przez wykonanie exit().
codeModuł jest dostępny w co najmniej Python v2.6, prawdopodobnie innych.
Zwykle używam tego podejścia w połączeniu z sygnałami do mojej pracy w Linuksie (dla Windows, patrz poniżej). Klepię to u góry moich skryptów Pythona:
import code
import signal
signal.signal(signal.SIGUSR2, lambda sig, frame: code.interact())
A następnie uruchom go z powłoki kill -SIGUSR2 <PID>, gdzie <PID>jest identyfikator procesu. Następnie proces zatrzymuje cokolwiek robi i przedstawia konsolę:
Python 2.6.2 (r262:71600, Oct 92009, 17:53:52)
[GCC 3.4.2] on linux2
Type "help", "copyright", "credits"or"license"for more information.
(InteractiveConsole)
>>>
Generalnie stamtąd ładuję komponent po stronie serwera zdalnego debuggera, taki jak doskonały WinPDB .
Brak zewnętrznych modułów (wszystkie standardowe rzeczy w Pythonie)
Ledwo zużywa zasoby, dopóki nie zostanie uruchomiony (import 2x)
Oto kod, którego używam w moim środowisku produkcyjnym, który załaduje stronę serwera WinPDB (jeśli jest dostępny) i wróci do otwierania konsoli Pythona.
# Break into a Python console upon SIGUSR1 (Linux) or SIGBREAK (Windows:# CTRL+Pause/Break). To be included in all production code, just in case.defdebug_signal_handler(signal, frame):del signal
del frame
try:
import rpdb2
printprintprint"Starting embedded RPDB2 debugger. Password is 'foobar'"printprint
rpdb2.start_embedded_debugger("foobar", True, True)
rpdb2.setbreak(depth=1)
returnexcept StandardError:
passtry:
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") orvars(signal).get("SIGUSR1"),
debug_signal_handler
)
except ValueError:
# Typically: ValueError: signal only works in main threadpass
Czy możesz podać więcej szczegółów na temat ładowania składnika WinPDB po stronie serwera, gdy masz konsolę Python?
Christian Long
1
Dodałem mój kod produkcyjny do odpowiedzi, ale zasadniczo wystarczy wprowadzić na konsoli tylko: '' import rpdb2; rpdb2.start_embedded_debugger ("foobar", True, True) '', a następnie uruchom GUI WinPDB z hasłem "foobar" po wyświetleniu monitu
RobM
26
Użyj powłoki pirasytu . Nie mogę uwierzyć, że działa tak dobrze, ale tak jest. „ Daj pid, zdobądź muszlę ”.
$ 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 222015, 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'
Powoduje to uruchomienie powłoki Pythona z dostępem do zmiennych globals () i locals () tego działającego procesu Pythona oraz innych wspaniałych rzeczy.
Testowałem to osobiście tylko na Ubuntu, ale wydaje się, że obsługuje również OSX.
Uwaga: Linia wyłączająca ptrace_scopewłaściwość jest konieczna tylko w przypadku jąder / systemów, które zostały zbudowane z włączoną funkcją CONFIG_SECURITY_YAMA. Uważaj, mieszając z ptrace_scope w wrażliwych środowiskach, ponieważ może to wprowadzić pewne luki w zabezpieczeniach. Zobacz tutaj po szczegóły.
@Dirk Uważam, że ptrace_scope jest niezbędne, aby umożliwić jednemu procesowi śledzenie / interakcję z innym niepowiązanym procesem.
python1981
Oczywiście dotyczy to tylko systemów z YAMA. Zaproponowałem zmianę i usunąłem mój oryginalny komentarz. (Ten również będzie dostępny w ciągu jakiegoś czasu.)
Dlaczego po prostu nie skorzystać z modułu pdb ? Pozwala zatrzymać skrypt, sprawdzić wartości elementów i wykonać kod linia po linii. A ponieważ jest oparty na interpreterze języka Python, zapewnia również funkcje oferowane przez klasyczny interpreter. Aby go użyć, po prostu umieść te 2 wiersze w swoim kodzie, w miejscu, w którym chcesz go zatrzymać i sprawdzić:
W przypadku większości dystrybucji Linuksa Python jest zbudowany z symboli debugowania, ale symbole debugowania znajdują się w innym pakiecie. Pakiet symboli debugowania można zainstalować po uruchomieniu skryptu Pythona.
W.Mann
1
Używając PyCharm, nie udało mi się połączyć z procesem w Ubuntu. Rozwiązaniem tego problemu jest wyłączenie YAMA. Aby uzyskać więcej informacji, zobacz askubuntu
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
Odpowiedzi:
Jeśli masz dostęp do kodu źródłowego programu, możesz stosunkowo łatwo dodać tę funkcjonalność.
Patrz przepis 576515 :
Debugging a running python process by interrupting and providing an interactive prompt (Python)
Cytować:
Kolejną implementację mniej więcej tej samej koncepcji zapewnia rconsole . Z dokumentacji:
from rfoo.utils import rconsole rconsole.spawn_server()
źródło
rfoo._rfoo.EofError: 0
Spowoduje to przerwanie procesu (chyba że uruchomisz go w wątku), ale możesz użyć
code
modułu do uruchomienia konsoli Pythona:import code code.interact()
Będzie to blokowane, dopóki użytkownik nie wyjdzie z konsoli interaktywnej przez wykonanie
exit()
.code
Moduł jest dostępny w co najmniej Python v2.6, prawdopodobnie innych.Zwykle używam tego podejścia w połączeniu z sygnałami do mojej pracy w Linuksie (dla Windows, patrz poniżej). Klepię to u góry moich skryptów Pythona:
import code import signal signal.signal(signal.SIGUSR2, lambda sig, frame: code.interact())
A następnie uruchom go z powłoki
kill -SIGUSR2 <PID>
, gdzie<PID>
jest identyfikator procesu. Następnie proces zatrzymuje cokolwiek robi i przedstawia konsolę: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) >>>
Generalnie stamtąd ładuję komponent po stronie serwera zdalnego debuggera, taki jak doskonały WinPDB .
Windows nie jest systemem operacyjnym zgodnym z POSIX , więc nie dostarcza takich samych sygnałów jak Linux. Jednak Python w wersji 2.2 i nowszych uwidacznia sygnał specyficzny dla systemu Windows
SIGBREAK
(wyzwalany przez naciśnięcieCTRL
+Pause/Break
). Ten sposób nie zakłócają normalnegoCTRL
+C
(SIGINT
) operacji, a więc jest przydatny alternatywy.Dlatego przenośna, ale nieco brzydka wersja powyższego to:
import code import signal signal.signal( vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"), lambda sig, frame: code.interact() )
Zalety tego podejścia:
Oto kod, którego używam w moim środowisku produkcyjnym, który załaduje stronę serwera WinPDB (jeśli jest dostępny) i wróci do otwierania konsoli Pythona.
# 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
źródło
Użyj powłoki pirasytu . Nie mogę uwierzyć, że działa tak dobrze, ale tak jest. „ Daj pid, zdobądź muszlę ”.
$ 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'
Powoduje to uruchomienie powłoki Pythona z dostępem do zmiennych globals () i locals () tego działającego procesu Pythona oraz innych wspaniałych rzeczy.
Testowałem to osobiście tylko na Ubuntu, ale wydaje się, że obsługuje również OSX.
Zaczerpnięte z tej odpowiedzi .
Uwaga: Linia wyłączająca
ptrace_scope
właściwość jest konieczna tylko w przypadku jąder / systemów, które zostały zbudowane z włączoną funkcjąCONFIG_SECURITY_YAMA
. Uważaj, mieszając z ptrace_scope w wrażliwych środowiskach, ponieważ może to wprowadzić pewne luki w zabezpieczeniach. Zobacz tutaj po szczegóły.źródło
Dlaczego po prostu nie skorzystać z modułu pdb ? Pozwala zatrzymać skrypt, sprawdzić wartości elementów i wykonać kod linia po linii. A ponieważ jest oparty na interpreterze języka Python, zapewnia również funkcje oferowane przez klasyczny interpreter. Aby go użyć, po prostu umieść te 2 wiersze w swoim kodzie, w miejscu, w którym chcesz go zatrzymać i sprawdzić:
import pdb pdb.set_trace()
źródło
Inna możliwość, bez dodawania rzeczy do skryptów Pythona, jest opisana tutaj:
https://wiki.python.org/moin/DebuggingWithGdb
Niestety, to rozwiązanie również wymaga przemyślenia, przynajmniej do tego stopnia, że musisz używać wersji Pythona z symbolami debugowania.
źródło
Używając PyCharm, nie udało mi się połączyć z procesem w Ubuntu. Rozwiązaniem tego problemu jest wyłączenie YAMA. Aby uzyskać więcej informacji, zobacz askubuntu
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
źródło