때때로이 파이썬 응용 프로그램이 붙어있어 어디에서 찾을 수 없습니다.
실행중인 정확한 코드를 보여주기 위해 Python 인터프리터에게 신호를 보내는 방법이 있습니까?
어떤 종류의 즉석 스택 트레이스?
관련 질문 :
때때로이 파이썬 응용 프로그램이 붙어있어 어디에서 찾을 수 없습니다.
실행중인 정확한 코드를 보여주기 위해 Python 인터프리터에게 신호를 보내는 방법이 있습니까?
어떤 종류의 즉석 스택 트레이스?
관련 질문 :
답변:
프로세스가 오랜 시간 동안 실행되지만 알 수없고 재현 할 수없는 이유로 때때로 멈추는 상황과 같은 상황에서 사용하는 모듈이 있습니다. 약간 해키이며 유닉스에서만 작동합니다 (신호 필요).
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
사용하려면 프로그램이 시작될 때 어느 시점에서 listen () 함수를 호출하십시오 (site.py에서 모든 파이썬 프로그램에서 사용하도록 할 수도 있습니다). 언제든지 kill을 사용하여 또는 파이썬으로 프로세스에 SIGUSR1 신호를 보냅니다.
os.kill(pid, signal.SIGUSR1)
이로 인해 프로그램이 현재있는 시점에서 파이썬 콘솔에 침입하여 스택 추적을 표시하고 변수를 조작 할 수 있습니다. control-d (EOF)를 사용하여 계속 실행합니다 (신호를 보내는 지점에서 I / O 등을 중단 할 수 있으므로 완전히 방해되지는 않습니다).
파이프를 통해 실행중인 프로세스와 통신하는 것을 제외하고 (백그라운드 프로세스 디버깅 등을 허용하는) 것을 제외하고 동일한 작업을 수행하는 또 다른 스크립트가 있습니다. 여기에 게시하기에는 약간 크지 만 파이썬 요리 책 레시피 로 추가했습니다 .
faulthandler
인터프리터 루프가 응답하지 않아도 Python 스택을 인쇄하는 C 레벨 신호 핸들러에 모듈 (및 PyPI에있는 백 포트)을 사용하십시오 .
신호 처리기를 설치하라는 제안은 좋은 것이며 많이 사용합니다. 예를 들어, bzr 은 기본적으로 SIGQUIT 핸들러를 설치 pdb.set_trace()
하여 즉시 pdb 프롬프트 에 놓도록 합니다. (자세한 내용은 bzrlib.breakin 모듈의 소스를 참조하십시오.) pdb를 사용하면 현재 스택 추적뿐만 아니라 변수 등도 검사 할 수 있습니다.
그러나 때로는 신호 처리기를 설치할 예측이없는 프로세스를 디버깅해야합니다. Linux에서는 gdb를 프로세스에 연결하고 일부 gdb 매크로로 파이썬 스택 추적을 얻을 수 있습니다. http://svn.python.org/projects/python/trunk/Misc/gdbinit를 에 넣고 ~/.gdbinit
다음을 수행하십시오.
gdb -p
PID
pystack
불행히도 완전히 신뢰할 만하지는 않지만 대부분의 경우 작동합니다.
마지막으로, 첨부 strace
는 프로세스가 수행하는 작업에 대한 좋은 아이디어를 제공 할 수 있습니다.
python-dbg
). 이러한 기호가 없으면 유용한 정보를 많이 얻지 못하는 것 같습니다.
Unable to locate python frame
각 명령으로 돌아갑니다
나는 거의 항상 여러 스레드를 다루고 있으며 주요 스레드는 일반적으로 많은 일을하지 않으므로 가장 흥미로운 것은 모든 스택을 덤프하는 것입니다 (Java의 덤프와 비슷합니다). 이 블로그를 기반으로 한 구현은 다음과 같습니다 .
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)
기호를 디버깅하지 않고 스톡 파이썬에서 실행 되는 준비되지 않은 파이썬 프로그램 의 스택 추적을 얻는 것은 pyrasite를 사용 하여 수행 할 수 있습니다 . 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
(@Albert의 팁은 다른 도구 중에서도 이에 대한 포인터가 포함되어 있습니다.)
dump_stacks.py
간단하게했다import traceback; traceback.print_stack()
traceback -l
사용할 수있는 사전 정의 된 Python 스크립트 목록을 제공 dump_stacks.py
하며 그 중 하나입니다. 스택 추적을 파일에 쓰는 등 자신 만의 것을 사용하는 경우 다른 이름을 사용하는 것이 좋습니다.
apt-get install gdb python-dbg
pyrasite를 실행하기 전에 실행하십시오. 그렇지 않으면 자동으로 실패합니다. 그렇지 않으면 매력처럼 작동합니다!
>>> import traceback
>>> def x():
>>> print traceback.extract_stack()
>>> x()
[('<stdin>', 1, '<module>', None), ('<stdin>', 2, 'x', None)]
스택 추적을 멋지게 포맷 할 수도 있습니다. 문서를 참조하십시오. .
편집 : @Douglas Leeder가 제안한대로 Java의 동작을 시뮬레이션하려면 다음을 추가하십시오.
import signal
import traceback
signal.signal(signal.SIGUSR1, lambda sig, stack: traceback.print_stack(stack))
응용 프로그램의 시작 코드에. 그런 다음 SIGUSR1
실행중인 Python 프로세스 로 보내 스택을 인쇄 할 수 있습니다 .
역 추적 모듈은 그 중 몇 가지 멋진 기능을 가지고 있습니다 : print_stack를 :
import traceback
traceback.print_stack()
import traceback; f = open('/tmp/stack-trace.log', 'w') traceback.print_stack(file=f) f.close()
결함 핸들러 모듈을 시도 할 수 있습니다 . 다음을 사용하여 설치 pip install faulthandler
하고 추가하십시오.
import faulthandler, signal
faulthandler.register(signal.SIGUSR1)
프로그램 시작시. 그런 다음 SIGUSR1을 프로세스 (ex :)로 보내 kill -USR1 42
모든 스레드의 Python 추적을 표준 출력에 표시하십시오. 설명서를 읽으십시오추가 옵션 (예 : 파일에 로그인) 및 역 추적을 표시하는 다른 방법에 를 .
이 모듈은 이제 Python 3.3의 일부입니다. Python 2의 경우 http://faulthandler.readthedocs.org/를 참조 하십시오.
여기에서 실제로 도움 이 된 것은 준비되지 않은 Python 프로세스 에서 스택 추적을 얻는 spiv의 팁입니다 (평판 포인트가 있으면 투표하고 의견을 말하겠습니다) . gdbinit 스크립트를 수정하기 전까지는 작동하지 않았다 . 그래서:
http://svn.python.org/projects/python/trunk/Misc/gdbinit를 다운로드 하여 설치하십시오~/.gdbinit
수정, 변경 [편집 : 더 이상 필요하지 않습니다; 링크 된 파일은 2010-01-14 기준으로 이미 변경되었습니다.]PyEval_EvalFrame
에PyEval_EvalFrameEx
gdb 첨부 : gdb -p PID
파이썬 스택 추적을 가져옵니다. pystack
No symbol "co" in current context.
나는 이것을 haridsv의 답변에 주석으로 추가 할 것입니다 하지만 그렇게 할 평판이 없다.
우리 중 일부는 여전히 2.6 이전의 Python 버전 (Thread.ident에 필요)에 붙어 있으므로 Python 2.5에서 스레드 코드가 표시되지는 않지만 코드가 작동합니다.
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)
faulthandler
Python 3.3의 새로운 기능인 모듈을 살펴보십시오 . Python 2에서 사용하기 위한 faulthandler
백 포트 는 PyPI에서 사용할 수 있습니다.
Solaris에서는 pstack (1)을 사용할 수 있습니다. 파이썬 코드를 변경할 필요가 없습니다. 예.
# 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.
pstack
같은 일을 하는 데비안 / 우분투 프로그램 이있는 것 같습니다
Linux 시스템에서 경우의 awesomeness에 사용 gdb
될 수 있습니다 (파이썬 디버그 확장자를 python-dbg
하거나python-debuginfo
패키지로 제공 . 또한 다중 스레드 응용 프로그램, GUI 응용 프로그램 및 C 모듈에 도움이됩니다.
다음을 사용하여 프로그램을 실행하십시오.
$ gdb -ex r --args python <programname>.py [arguments]
이것은 gdb
준비 python <programname>.py <arguments>
하고 r
해제 하도록 지시 합니다.
이제 프로그램이 멈 추면 gdb
콘솔 로 전환하고을 누르고 Ctr+C실행하십시오.
(gdb) thread apply all py-list
스레드를 디버깅하는 솔루션을 잠시 찾고 있었고 haridsv 덕분에 여기에서 찾았습니다. 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)
내 필요에 따라 이름으로 스레드를 필터링합니다.
나는 실행중인 파이썬 프로세스에 연결하고 파이썬 쉘을 얻기 위해 코드를 주입하는 도구를 함께 해킹했다.
여기를 참조하십시오 : https://github.com/albertz/pydbattach
pyrasite
완벽하게 작동했습니다!
훌륭한 py-spy 로 수행 할 수 있습니다 . 그것은이다 파이썬 프로그램에 대한 샘플링 프로파일 러 의 작업이 파이썬 프로세스에 연결하고 자신의 콜 스택을 샘플링하는 것입니다, 그래서. 따라서 프로세스 py-spy dump --pid $SOME_PID
에서 모든 스레드의 호출 스택을 덤프하기 위해 수행해야하는 모든 것 $SOME_PID
입니다. 일반적으로 대상 프로세스의 메모리를 읽으려면 에스컬레이션 된 권한이 필요합니다.
다음은 스레드 된 Python 응용 프로그램의 모습에 대한 예입니다.
$ sudo py-spy dump --pid 31080
Process 31080: python3.7 -m chronologer -e production serve -u www-data -m
Python v3.7.1 (/usr/local/bin/python3.7)
Thread 0x7FEF5E410400 (active): "MainThread"
_wait (cherrypy/process/wspbus.py:370)
wait (cherrypy/process/wspbus.py:384)
block (cherrypy/process/wspbus.py:321)
start (cherrypy/daemon.py:72)
serve (chronologer/cli.py:27)
main (chronologer/cli.py:84)
<module> (chronologer/__main__.py:5)
_run_code (runpy.py:85)
_run_module_as_main (runpy.py:193)
Thread 0x7FEF55636700 (active): "_TimeoutMonitor"
run (cherrypy/process/plugins.py:518)
_bootstrap_inner (threading.py:917)
_bootstrap (threading.py:885)
Thread 0x7FEF54B35700 (active): "HTTPServer Thread-2"
accept (socket.py:212)
tick (cherrypy/wsgiserver/__init__.py:2075)
start (cherrypy/wsgiserver/__init__.py:2021)
_start_http_thread (cherrypy/process/servers.py:217)
run (threading.py:865)
_bootstrap_inner (threading.py:917)
_bootstrap (threading.py:885)
...
Thread 0x7FEF2BFFF700 (idle): "CP Server Thread-10"
wait (threading.py:296)
get (queue.py:170)
run (cherrypy/wsgiserver/__init__.py:1586)
_bootstrap_inner (threading.py:917)
_bootstrap (threading.py:885)
피 링지 은 사전 설정없이 실행중인 파이썬 프로세스, 인쇄 스택 추적, 변수 등과 상호 작용할 수있는 디버거입니다.
과거에는 신호 처리기 솔루션을 자주 사용했지만 특정 환경에서는 여전히 문제를 재현하기가 어려울 수 있습니다.
pyrasite
는 나를 위해 매력처럼 작동했습니다.
실행중인 파이썬 프로세스에 연결하여 합리적인 결과를 얻을 수있는 방법이 없습니다. 프로세스가 잠기면 내가하는 일은 strace에 연결되어 정확히 무슨 일이 일어나고 있는지 파악하려고합니다.
불행히도 strace는 경쟁 조건을 "고정"하여 결과물도 쓸모 없게하는 관찰자입니다.
이를 위해 curses 인터페이스가있는 Python 디버거 인 PuDB 를 사용할 수 있습니다 . 그냥 추가
from pudb import set_interrupt_handler; set_interrupt_handler()
중단하고 싶을 때 Ctrl-C를 사용하십시오. 당신이 c
그것을 그리워하고 다시 시도하려는 경우 계속하고 여러 번 다시 휴식을 취할 수 있습니다 .
파이썬 확장 프로그램을 사용하여 GDB 캠프에 있습니다. 팔로우 https://wiki.python.org/moin/DebuggingWithGdb 수단
dnf install gdb python-debuginfo
또는 sudo apt-get install gdb python2.7-dbg
gdb python <pid of running process>
py-bt
또한 고려 info threads
하고 thread apply all py-bt
.
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.
실행할 때 와 같은 응답을 얻는 것이 정상 입니까? py-bt
gdb
sudo
입니다. gdb pyton <pid>
나도 sudo 로 달릴 필요가 있었다 .
SIGQUIT에 대한 java의 응답 과 비슷한 것을 알지 못 하므로 응용 프로그램에 빌드해야 할 수도 있습니다. 어쩌면 어떤 종류의 메시지에 대한 응답으로 스택 추적을 얻을 수있는 다른 스레드에서 서버를 만들 수 있습니까?
Python 3에서 pdb는 디버거에서 c (ont (inue))를 처음 사용할 때 자동으로 신호 처리기를 설치합니다. 나중에 Control-C를 누르면 바로 거기로 돌아갑니다. Python 2에는 비교적 오래된 버전에서도 작동 해야하는 하나의 라이너가 있습니다 (2.7에서 테스트되었지만 Python 소스를 다시 2.4로 확인했는데 정상적으로 보였습니다).
import pdb, signal
signal.signal(signal.SIGINT, lambda sig, frame: pdb.Pdb().set_trace(frame))
파이썬을 디버깅하는 데 많은 시간을 할애한다면 pdb는 배울 가치가 있습니다. 이 인터페이스는 약간 애매하지만 gdb와 같은 유사한 도구를 사용한 사람에게는 친숙해야합니다.
uWSGI를 사용 하여이 작업을 수행 해야하는 경우 Python Tracebacker가 내장되어 있으며 구성에서 활성화해야합니다 (번호는 각 작업자의 이름에 붙어 있습니다).
py-tracebacker=/var/run/uwsgi/pytrace
이 작업을 완료하면 소켓에 연결하여 간단히 역 추적을 인쇄 할 수 있습니다.
uwsgi --connect-and-read /var/run/uwsgi/pytrace1