Mam tę aplikację Python, która od czasu do czasu zacina się i nie mogę się dowiedzieć, gdzie.
Czy jest jakiś sposób, aby zasygnalizować interpreterowi języka Python, aby pokazał dokładnie działający kod?
Jakiś rodzaj śledzenia stosu w locie?
Powiązane pytania:
Odpowiedzi:
Mam moduł, którego używam do takich sytuacji - gdzie proces będzie działał przez długi czas, ale czasami utknie z nieznanych i nieodwracalnych powodów. Jest nieco zhackowany i działa tylko na Uniksie (wymaga sygnałów):
Aby użyć, po prostu wywołaj funkcję Listen () w pewnym momencie, gdy program się uruchamia (możesz nawet umieścić go w site.py, aby wszystkie programy python go używały) i pozwolić mu działać. W dowolnym momencie wyślij procesowi sygnał SIGUSR1, używając kill lub w pythonie:
Spowoduje to, że program przejdzie do konsoli Pythona w punkcie, w którym się aktualnie znajduje, pokazując ślad stosu i umożliwiając manipulowanie zmiennymi. Użyj control-d (EOF), aby kontynuować działanie (choć zauważ, że prawdopodobnie przerwiesz każde wejście / wyjście itp. W miejscu, w którym zasygnalizujesz, więc nie jest to w pełni nieinwazyjne.
Mam inny skrypt, który robi to samo, tyle że komunikuje się z uruchomionym procesem za pomocą potoku (aby umożliwić debugowanie procesów w tle itp.). Jest tu trochę za dużo, ale dodałem go jako przepis na książkę kucharską w języku Python .
źródło
faulthandler
modułu (i jego backportu znalezionego w PyPI) do obsługi sygnału poziomu C, która wydrukuje stos Pythona bez konieczności reagowania na pętlę interpretera.Sugestia zainstalowania modułu obsługi sygnałów jest dobra i bardzo go używam. Na przykład, bzr domyślnie instaluje moduł obsługi SIGQUIT , który wywołuje
pdb.set_trace()
natychmiastowe upuszczenie do monitu pdb . (Zobacz bzrlib.breakin Dokładne szczegóły znajdują się modułu .) Dzięki pdb możesz nie tylko uzyskać bieżący ślad stosu, ale także sprawdzić zmienne itp.Czasami jednak muszę debugować proces, w którym nie miałem zdolności przewidywania, aby zainstalować moduł obsługi sygnału. W systemie Linux możesz dołączyć proces gdb do procesu i uzyskać ślad stosu Pythona za pomocą niektórych makr gdb. Umieścić http://svn.python.org/projects/python/trunk/Misc/gdbinit w
~/.gdbinit
, a następnie:gdb -p
PID
pystack
Niestety nie jest całkowicie niezawodny, ale działa przez większość czasu.
Wreszcie, dołączanie
strace
często daje dobry obraz tego, co robi proces.źródło
python-dbg
). Bez tych symboli nie wydaje się, aby uzyskać wiele użytecznych informacji.Unable to locate python frame
do każdego poleceniaPrawie zawsze mam do czynienia z wieloma wątkami, a główny wątek na ogół niewiele robi, więc najciekawsze jest zrzucenie wszystkich stosów (co bardziej przypomina zrzut Java). Oto implementacja oparta na tym blogu :
źródło
Uzyskiwanie śladu stosu nieprzygotowanego programu python, działającego w podstawowym pythonie bez symboli debugowania, można wykonać za pomocą pirazytu . Działa jak urok dla mnie w Ubuntu Trusty:
(Hat tip do @Albert, którego odpowiedź zawierała między innymi wskaźnik do tego).
źródło
dump_stacks.py
był po prostuimport traceback; traceback.print_stack()
traceback -l
zawiera listę predefiniowanych skryptów Pythona, których możesz użyć, idump_stacks.py
jest jednym z nich. Jeśli używasz własnego (na przykład do zapisywania śladu stosu w pliku), rozsądnie może być użycie innej nazwy.apt-get install gdb python-dbg
(lub odpowiednik) przed uruchomieniem pirazytu, w przeciwnym razie po cichu zawiedzie. W przeciwnym razie działa jak urok!Możesz również ładnie sformatować ślad stosu, zobacz dokumenty .
Edycja : Aby zasymulować zachowanie Javy, zgodnie z sugestią @Douglas Leeder, dodaj:
do kodu startowego w aplikacji. Następnie możesz wydrukować stos, wysyłając
SIGUSR1
go do działającego procesu Python.źródło
Traceback Moduł posiada kilka ciekawych funkcji, wśród nich: print_stack:
źródło
import traceback; f = open('/tmp/stack-trace.log', 'w') traceback.print_stack(file=f) f.close()
Możesz wypróbować moduł obsługi błędów . Zainstaluj go za pomocą
pip install faulthandler
i dodaj:na początku twojego programu. Następnie wyślij SIGUSR1 do swojego procesu (np .:), aby
kill -USR1 42
wyświetlić śledzenie wszystkich wątków Pythona na standardowym wyjściu. Przeczytaj dokumentację, aby uzyskać więcej opcji (np .: zaloguj się do pliku) i inne sposoby wyświetlania śledzenia.Moduł jest teraz częścią Python 3.3. W przypadku Python 2 zobacz http://faulthandler.readthedocs.org/
źródło
To, co naprawdę mi pomogło, to wskazówka spiv (którą głosowałbym i komentowałbym, gdybym miał punkty reputacji), aby uzyskać ślad stosu z nieprzygotowanego procesu Pythona. Tyle że nie działało, dopóki nie zmodyfikowałem skryptu gdbinit . Więc:
pobierz http://svn.python.org/projects/python/trunk/Misc/gdbinit i włóż
~/.gdbinit
edytuj, zmieniając[edycja: nie jest już potrzebne; plik połączony ma już tę zmianę na dzień 14.01.2010]PyEval_EvalFrame
naPyEval_EvalFrameEx
Dołącz gdb:
gdb -p PID
Uzyskaj śledzenie stosu python:
pystack
źródło
No symbol "co" in current context.
Dodałbym to jako komentarz do odpowiedzi haridsv , ale brakuje mi reputacji, aby to zrobić:
Niektórzy z nas nadal tkwią w wersji Pythona starszej niż 2.6 (wymagana dla Thread.ident), więc dostałem kod działający w Pythonie 2.5 (choć bez wyświetlania nazwy wątku) jako taki:
źródło
python -dv twójscript.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ś go uruchomić w następujący sposób:
python -m pdb yourscript.py
Mówi to interpreterowi Pythona o uruchomieniu skryptu z modułem „pdb”, który jest debuggerem Pythona, jeśli uruchomisz go w ten sposób, interpreter zostanie uruchomiony w trybie interaktywnym, podobnie jak GDB
źródło
Spójrz na
faulthandler
moduł, nowy w Pythonie 3.3.faulthandler
Backport do użytku w Pythonie 2 jest dostępny na PyPI.źródło
W systemie Solaris można używać pstack (1). Nie są wymagane żadne zmiany w kodzie Pythona. na przykład.
źródło
pstack
który robi to samoJeśli korzystasz z systemu Linux, skorzystaj z niesamowitości
gdb
dzięki rozszerzeniom debugowania Pythona (może być wpython-dbg
lub wpython-debuginfo
pakiecie). Pomaga również w aplikacjach wielowątkowych, aplikacjach GUI i modułach C.Uruchom swój program z:
To instruuje, jak
gdb
go przygotowaćpython <programname>.py <arguments>
ir
usunąć.Teraz, kiedy program zawiesi się, przełącz się na
gdb
konsolę, naciśnij Ctr+Ci wykonaj:Zobacz przykładową sesję i więcej informacji tutaj i tutaj .
źródło
Przez jakiś czas szukałem rozwiązania do debugowania moich wątków i znalazłem je tutaj dzięki haridsv. Używam nieco uproszczonej wersji wykorzystującej traceback.print_stack ():
Na moje potrzeby filtruję wątki według nazwy.
źródło
Warto spojrzeć na Pydb , „rozszerzoną wersję debugera Pythona luźno opartą na zestawie poleceń gdb”. Obejmuje menedżerów sygnałów, którzy mogą zadbać o uruchomienie debuggera po wysłaniu określonego sygnału.
Projekt Summer of Code z 2006 r. Dotyczył dodania funkcji zdalnego debugowania do pydb w module o nazwie mpdb .
źródło
Zhakowałem razem narzędzie, które dołącza się do działającego procesu Pythona i wstrzykuję trochę kodu, aby uzyskać powłokę Pythona.
Zobacz tutaj: https://github.com/albertz/pydbattach
źródło
pyrasite
działało idealnie!Można to zrobić za pomocą doskonałego py-spy . Jest to profiler do próbkowania dla programów w języku Python , więc jego zadaniem jest dołączanie do procesów w języku Python i próbkowanie stosów wywołań. Dlatego
py-spy dump --pid $SOME_PID
wszystko, co musisz zrobić, aby zrzucić stosy wywołań wszystkich wątków w tym$SOME_PID
procesie. Zazwyczaj potrzebuje eskalowanych uprawnień (do odczytu pamięci procesu docelowego).Oto przykład tego, jak to wygląda w wątkowej aplikacji Python.
źródło
pyringe to debugger, który może wchodzić w interakcje z uruchomionymi procesami Pythona, drukować ślady stosu, zmienne itp. bez konieczności wcześniejszej konfiguracji.
Chociaż w przeszłości często korzystałem z rozwiązania do obsługi sygnałów, w niektórych środowiskach wciąż może być trudno odtworzyć problem.
źródło
pyrasite
działał dla mnie jak urok.Nie ma sposobu, aby podłączyć się do uruchomionego procesu Pythona i uzyskać rozsądne wyniki. To, co robię, jeśli procesy się blokują, to podłączanie się do sieci i próba ustalenia, co dokładnie się dzieje.
Niestety często strace jest obserwatorem, który „naprawia” warunki wyścigu, dzięki czemu dane wyjściowe są również bezużyteczne.
źródło
W tym celu można użyć PuDB , debuggera w języku Python z interfejsem programu curses. Poprostu dodaj
do swojego kodu i użyj Ctrl-C, gdy chcesz się zepsuć. Możesz kontynuować
c
i przerwać ponownie wiele razy, jeśli go przegapisz i chcesz spróbować ponownie.źródło
Jestem w obozie GDB z rozszerzeniami python. Postępuj zgodnie z https://wiki.python.org/moin/DebuggingWithGdb , co oznacza
dnf install gdb python-debuginfo
lubsudo apt-get install gdb python2.7-dbg
gdb python <pid of running process>
py-bt
Weź również pod uwagę
info threads
ithread apply all py-bt
.źródło
Traceback (most recent call first): Python Exception <class 'gdb.error'> No frame is currently selected.: Error occurred in Python command: No frame is currently selected.
podczas pracypy-bt
wgdb
?sudo
.gdb pyton <pid>
Musiałem też uruchomić jako sudo.Jak debugować dowolną funkcję w konsoli :
Utwórz funkcję, w której używasz pdb.set_trace () , a następnie funkcję, którą chcesz debugować.
Następnie wywołaj utworzoną funkcję:
Miłego debugowania :)
źródło
Nie znam niczego podobnego do odpowiedzi Javy na SIGQUIT , więc może być konieczne wbudowanie go w aplikację. Może mógłbyś stworzyć serwer w innym wątku, który może uzyskać ślad stosu w odpowiedzi na wiadomość?
źródło
użyj modułu inspekcji.
stos (kontekst = 1) Zwraca listę rekordów stosu ponad ramką dzwoniącego.
Uważam to za bardzo pomocne.
źródło
W Pythonie 3 pdb automatycznie zainstaluje moduł obsługi sygnałów przy pierwszym użyciu c (ont (inue)) w debuggerze. Naciśnięcie przycisku Control-C spowoduje powrót do tego miejsca. W Pythonie 2 znajduje się jedna linijka, która powinna działać nawet w stosunkowo starych wersjach (testowana w wersji 2.7, ale sprawdziłem źródła Pythona z powrotem do wersji 2.4 i wyglądało to dobrze):
pdb warto się nauczyć, jeśli poświęcasz trochę czasu na debugowanie Pythona. Interfejs jest nieco tępy, ale powinien być znany każdemu, kto używał podobnych narzędzi, takich jak gdb.
źródło
Jeśli musisz to zrobić z uWSGI, ma on wbudowany Python Tracebacker i wystarczy włączyć go w konfiguracji (numer jest dołączony do nazwy dla każdego pracownika):
Po wykonaniu tej czynności możesz wydrukować ślad, po prostu podłączając się do gniazda:
źródło
W miejscu, w którym kod jest uruchamiany, możesz wstawić ten mały fragment kodu, aby zobaczyć ładnie sformatowany ślad wydruku stosu. Zakłada się, że masz folder o nazwie
logs
w katalogu głównym projektu.źródło