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:

Author: Community, 2008-09-25

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 .

 294
Author: Brian,
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
Niestety nie jest do końca niezawodny, ale działa przez większość czasu.

Wreszcie, dołączanie strace często daje dobre wyobrażenie o tym, co robi dany proces.

 137
Author: spiv,
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)
 63
Author: haridsv,
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.)

 40
Author: Nickolay,
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.

 33
Author: Torsten Marek,
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()
 26
Author: gulgi,
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 PyEval_EvalFrame na PyEval_EvalFrameEx [edit: no longer needed; the linked file ma już tę zmianę od 2010-01-14]

  • Dołącz gdb: gdb -p PID

  • Pobierz ślad stosu Pythona: pystack

 19
Author: Gunnlaugur Briem,
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/

 19
Author: haypo,
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

 10
Author: Gustavo Rubio,
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)
 10
Author: Konstantin Naryshkin,
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.

 8
Author: Matt Joiner,
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.
 6
Author: Tim Foster,
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 run 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 .

 6
Author: anatoly techtonik,
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.

 5
Author: Stefan,
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 .

 3
Author: rcoup,
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

 3
Author: Albert,
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.

 2
Author: Dan Lecocq,
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.

 1
Author: Armin Ronacher,
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.

 1
Author: asmeurer,
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ść?

 0
Author: Douglas Leeder,
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.

 0
Author: Alison R.,
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.

 0
Author: jtatum,
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
 0
Author: Michal Čihař,
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

  1. dnf install gdb python-debuginfo LUB sudo apt-get install gdb python2.7-dbg
  2. gdb python <pid of running process>
  3. py-bt

Rozważmy również info threads i thread apply all py-bt.

 0
Author: user7610,
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