Wyświetlanie śladu stosu z uruchomionej aplikacji Pythona
Mam taką aplikację Pythona, która od czasu do czasu utkwiła i nie mogę się dowiedzieć gdzie.
Czy Jest jakiś sposób na sygnalizację interpretera Pythona, aby pokazać ci dokładny kod, który działa?
Jakiś stacktrace w locie?
powiązane pytania:
24 answers
Mam moduł, którego używam w takich sytuacjach - gdzie proces będzie działał przez długi czas, ale czasami utknie z nieznanych i nieodwracalnych powodów. Jest nieco hakerski i działa tylko na Uniksie (wymaga sygnałów):
import code, traceback, signal
def debug(sig, frame):
"""Interrupt running process, and provide a python prompt for
interactive debugging."""
d={'_frame':frame} # Allow access to frame object.
d.update(frame.f_globals) # Unless shadowed by global
d.update(frame.f_locals)
i = code.InteractiveConsole(d)
message = "Signal received : entering python shell.\nTraceback:\n"
message += ''.join(traceback.format_stack(frame))
i.interact(message)
def listen():
signal.signal(signal.SIGUSR1, debug) # Register handler
Aby użyć, po prostu wywołaj funkcję listen() w pewnym momencie, gdy twój program się uruchomi (możesz nawet włożyć ją w site.py aby wszystkie programy Pythona z niego korzystały) i pozwolić mu działać. W dowolnym momencie, wysłać procesowi sygnał SIGUSR1, używając kill, lub w python:
os.kill(pid, signal.SIGUSR1)
Spowoduje to, że program przełączy się na konsolę Pythona w miejscu, w którym jest aktualnie, pokazując ślad stosu i umożliwiając manipulowanie zmiennymi. Użyj control-d (EOF), aby kontynuować działanie (chociaż zauważ, że prawdopodobnie przerwiesz wszystkie wejścia/wyjścia itp.w momencie sygnału, więc nie jest to całkowicie nieinwazyjne.
Mam inny skrypt, który robi to samo, z tym, że komunikuje się z uruchomionym procesem przez rurę (aby umożliwić debugowanie procesy tła itp.). Jest trochę duży, aby pisać tutaj, ale dodałem go jako Python Cookbook recipe .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-10 16:05:19
Sugestia instalacji obsługi sygnału jest dobra i często z niej korzystam. Na przykład bzr domyślnie instaluje funkcję obsługi SIGQUIT, która wywołuje pdb.set_trace()
, aby natychmiast wrzucić Cię do monitu pdb. (Patrz bzrlib.źródło modułu breakin dla dokładnych szczegółów.) Dzięki pdb możesz nie tylko uzyskać bieżący ślad stosu, ale także sprawdzić zmienne itp.
Jednak czasami muszę debugować proces, którego nie miałem na myśli, aby zainstalować włączam obsługę sygnału. W Linuksie możesz dołączyć gdb do procesu i uzyskać ślad stosu Pythona z niektórymi makrami gdb. Put http://svn.python.org/projects/python/trunk/Misc/gdbinit W ~/.gdbinit
, następnie:
- Dołącz gdb:
gdb -p
PID
- Pobierz ślad stosu Pythona:
pystack
Wreszcie, dołączanie strace
często daje dobre wyobrażenie o tym, co robi dany proces.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-01 14:02:31
Prawie zawsze mam do czynienia z wieloma wątkami, a główny wątek generalnie nie robi zbyt wiele, więc najciekawsze jest zrzucenie wszystkich stosów (co jest bardziej podobne do zrzutu Javy). Oto implementacja oparta na tego bloga :
import threading, sys, traceback
def dumpstacks(signal, frame):
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
code = []
for threadId, stack in sys._current_frames().items():
code.append("\n# Thread: %s(%d)" % (id2name.get(threadId,""), threadId))
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
if line:
code.append(" %s" % (line.strip()))
print "\n".join(code)
import signal
signal.signal(signal.SIGQUIT, dumpstacks)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-07 06:29:09
Uzyskanie śladu stosu nieprzygotowanegoprogramu Pythona, działającego w Pythonie stockowym bez debugowania symbolimożna wykonać za pomocą pyrasite. Działa jak urok dla mnie w Ubuntu Trusty:
$ sudo pip install pyrasite
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
$ sudo pyrasite 16262 dump_stacks.py # dumps stacks to stdout/stderr of the python program
(Hat tip do @ Albert, którego odpowiedź zawierała wskaźnik do tego, między innymi.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-26 18:22:20
>>> import traceback
>>> def x():
>>> print traceback.extract_stack()
>>> x()
[('<stdin>', 1, '<module>', None), ('<stdin>', 2, 'x', None)]
Możesz również ładnie sformatować ślad stosu, Zobacz docs.
Edit: aby symulować zachowanie Javy, zgodnie z sugestią @ Douglas Leeder, dodaj to:
import signal
import traceback
signal.signal(signal.SIGUSR1, lambda sig, stack: traceback.print_stack(stack))
Do kodu startowego w Twojej aplikacji. Następnie możesz wydrukować stos wysyłając SIGUSR1
do uruchomionego procesu Pythona.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 09:32:24
The traceback Moduł ma kilka ciekawych funkcji, wśród nich: print_stack:
import traceback
traceback.print_stack()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-04 00:29:50
To, co naprawdę pomogło mi tutaj, to wskazówka spiva (którą bym zagłosował i skomentował, gdybym miał punkty reputacji) za uzyskanie śladu stosu z nieprzygotowanego procesu Pythona. Tylko, że nie zadziałało, dopóki nie zmodyfikowałem skryptu gdbinit . Więc:
Pobierz http://svn.python.org/projects/python/trunk/Misc/gdbinit i umieścić go w
~/.gdbinit
edytuj, zmieniając[edit: no longer needed; the linked file ma już tę zmianę od 2010-01-14]PyEval_EvalFrame
naPyEval_EvalFrameEx
Dołącz gdb:
gdb -p PID
Pobierz ślad stosu Pythona:
pystack
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:17
Możesz spróbować modułu faulthandler. Zainstaluj go używając pip install faulthandler
i dodaj:
import faulthandler, signal
faulthandler.register(signal.SIGUSR1)
Na początku programu. Następnie wyślij SIGUSR1 do procesu (np: kill -USR1 42
), aby wyświetlić ślad wszystkich wątków Pythona na standardowe wyjście. przeczytaj dokumentację , aby uzyskać więcej opcji (np. Zaloguj się do pliku) i inne sposoby wyświetlania traceback.
Moduł jest teraz częścią Pythona 3.3. Python 2, Zobacz http://faulthandler.readthedocs.org/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-03 14:54:03
python-dv yourscript.py
To sprawi, że interpreter będzie działał w trybie debugowania i da ci ślad tego, co robi interpreter.
Jeśli chcesz interaktywnie debugować kod, powinieneś uruchomić go w następujący sposób:
python-m pdb yourscript.py
To mówi interpreterowi Pythona, aby uruchomił Twój skrypt z modułem "pdb" , który jest debuggerem Pythona, jeśli go uruchomisz w ten sposób, interpreter zostanie uruchomiony w trybie interaktywnym, dużo jak GDB
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 08:24:24
Dodałbym to jako komentarz do odpowiedzi haridsv , ale brakuje mi reputacji, aby to zrobić:
Niektórzy z nas wciąż tkwią w wersji Pythona starszej niż 2.6 (wymagana dla wątku.ident), więc kod działa w Pythonie 2.5 (choć bez wyświetlania nazwy wątku) jako taki:
import traceback
import sys
def dumpstacks(signal, frame):
code = []
for threadId, stack in sys._current_frames().items():
code.append("\n# Thread: %d" % (threadId))
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
if line:
code.append(" %s" % (line.strip()))
print "\n".join(code)
import signal
signal.signal(signal.SIGQUIT, dumpstacks)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:14
Spójrz na faulthandler
moduł, nowość w Pythonie 3.3. A faulthandler
backport do użycia w Pythonie 2 jest dostępny na PyPI.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-14 20:09:37
Na Solarisie można użyć pstack(1) żadne zmiany w kodzie Pythona nie są konieczne. np.
# pstack 16000 | grep : | head
16000: /usr/bin/python2.6 /usr/lib/pkg.depotd --cfg svc:/application/pkg/serv
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:282 (_wait) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:295 (wait) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:242 (block) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/_init_.py:249 (quickstart) ]
[ /usr/lib/pkg.depotd:890 (<module>) ]
[ /usr/lib/python2.6/threading.py:256 (wait) ]
[ /usr/lib/python2.6/Queue.py:177 (get) ]
[ /usr/lib/python2.6/vendor-packages/pkg/server/depot.py:2142 (run) ]
[ /usr/lib/python2.6/threading.py:477 (run)
etc.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-28 21:30:38
Jeśli korzystasz z systemu Linux, użyj awesomeness gdb
z rozszerzeniami debugowania Pythona (może być w pakiecie python-dbg
lub python-debuginfo
). Pomaga również w aplikacjach wielowątkowych, aplikacjach GUI i modułach C.
Uruchom program za pomocą:
$ gdb -ex r --args python <programname>.py [arguments]
To nakazuje gdb
przygotować python <programname>.py <arguments>
i r
un it.
Teraz, gdy program się zawiesza, przełącz się na konsolę gdb
, Naciśnij Ctr+C i wykonaj:
(gdb) thread apply all py-list
Zobacz przykładowa sesja i więcej informacji tutaj i tutaj .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-24 08:08:48
Szukałem jakiegoś rozwiązania do debugowania moich wątków i znalazłem go tutaj dzięki haridsv. Używam nieco uproszczonej wersji wykorzystującej traceback.print_stack ():
import sys, traceback, signal
import threading
import os
def dumpstacks(signal, frame):
id2name = dict((th.ident, th.name) for th in threading.enumerate())
for threadId, stack in sys._current_frames().items():
print(id2name[threadId])
traceback.print_stack(f=stack)
signal.signal(signal.SIGQUIT, dumpstacks)
os.killpg(os.getpgid(0), signal.SIGQUIT)
Dla moich potrzeb filtruję również wątki po nazwie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-03 12:46:04
Warto przyjrzeć się Pydb, "rozbudowanej wersji debuggera Pythona luźno opartej na zestawie komend gdb". Zawiera Menedżery sygnałów, które mogą zadbać o uruchomienie debuggera po wysłaniu określonego sygnału.
Projekt Summer of Code z 2006 roku polegał na dodaniu funkcji zdalnego debugowania do pydb w module mpdb .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-29 01:28:29
Zhakowałem narzędzie, które dołącza się do uruchomionego procesu Pythona i wstrzykuje kod, aby uzyskać powłokę Pythona.
Zobacz tutaj: https://github.com/albertz/pydbattach
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-06 18:49:30
Pyringe jest debugerem, który może wchodzić w interakcje z uruchomionymi procesami Pythona, drukować ślady stosu, zmienne itp. bez żadnej konfiguracji a priori.
Chociaż często używałem rozwiązania obsługi sygnału w przeszłości, nadal często może być trudno odtworzyć problem w niektórych środowiskach.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-01 09:40:07
Nie ma sposobu, aby podłączyć się do uruchomionego procesu Pythona i uzyskać rozsądne wyniki. To, co robię, gdy processes lock up, podpina strace ' a i próbuje dowiedzieć się, co dokładnie się dzieje.
Niestety często strace jest obserwatorem, który "naprawia" warunki wyścigu tak, że wyjście jest bezużyteczne również tam.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 09:09:54
Możesz użyć PuDB, debuggera Pythona z interfejsem curses. Wystarczy dodać
from pudb import set_interrupt_handler; set_interrupt_handler()
Do kodu i użyj Ctrl-C, gdy chcesz złamać. Możesz kontynuować z c
i złamać ponownie wiele razy, jeśli przegapisz go i chcesz spróbować ponownie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-27 00:54:57
Nie znam niczego podobnego do odpowiedzi Javy na SIGQUIT , więc być może będziesz musiał ją wbudować w swoją aplikację. Może mógłbyś zrobić serwer w innym wątku, który może dostać stacktrace na odpowiedź na jakąś wiadomość?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 09:06:39
Użyj modułu inspect.
Import pomoc(insp.stos) Pomoc na stosie funkcji w module inspect:
Stack (context=1) Zwraca listę rekordów stosu nad ramką wywołującego.
Uważam to za bardzo pomocne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-21 16:42:05
W Pythonie 3, pdb automatycznie zainstaluje obsługę sygnału przy pierwszym użyciu C(ont (inue)) w debuggerze. Naciśnięcie przycisku Control-C spowoduje, że zostaniesz tam z powrotem. W Pythonie 2, Oto jednolinijkowy, który powinien działać nawet w stosunkowo starych wersjach (testowany w 2.7, ale sprawdziłem źródło Pythona z powrotem do 2.4 i wyglądało to dobrze): {]}
import pdb, signal
signal.signal(signal.SIGINT, lambda sig, frame: pdb.Pdb().set_trace(frame))
Pdb jest wart nauki, jeśli poświęcasz dowolną ilość czasu na debugowanie Pythona. Interfejs jest nieco rozwarty, ale powinien być znany każdemu który używał podobnych narzędzi, takich jak gdb.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-14 02:16:25
W przypadku, gdy trzeba to zrobić z uWSGI, ma on wbudowany Python Tracebacker i tylko kwestia włączenia go w konfiguracji (numer jest dołączony do nazwy każdego workera):
py-tracebacker=/var/run/uwsgi/pytrace
Gdy to zrobisz, możesz wydrukować backtrace po prostu łącząc się z gniazdem:
uwsgi --connect-and-read /var/run/uwsgi/pytrace1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-28 06:15:05
Jestem w obozie GDB z rozszerzeniami Pythona. Follow https://wiki.python.org/moin/DebuggingWithGdb , CZYLI
-
dnf install gdb python-debuginfo
LUBsudo apt-get install gdb python2.7-dbg
gdb python <pid of running process>
py-bt
Rozważmy również info threads
i thread apply all py-bt
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-18 12:31:10