[python] 실행중인 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 등을 중단 할 수 있으므로 완전히 방해되지는 않습니다).

파이프를 통해 실행중인 프로세스와 통신하는 것을 제외하고 (백그라운드 프로세스 디버깅 등을 허용하는) 것을 제외하고 동일한 작업을 수행하는 또 다른 스크립트가 있습니다. 여기에 게시하기에는 약간 크지 만 파이썬 요리 책 레시피 로 추가했습니다 .


답변

신호 처리기를 설치하라는 제안은 좋은 것이며 많이 사용합니다. 예를 들어, bzr 은 기본적으로 SIGQUIT 핸들러를 설치 pdb.set_trace()하여 즉시 pdb 프롬프트 에 놓도록 합니다. (자세한 내용은 bzrlib.breakin 모듈의 소스를 참조하십시오.) pdb를 사용하면 현재 스택 추적뿐만 아니라 변수 등도 검사 할 수 있습니다.

그러나 때로는 신호 처리기를 설치할 예측이없는 프로세스를 디버깅해야합니다. Linux에서는 gdb를 프로세스에 연결하고 일부 gdb 매크로로 파이썬 스택 추적을 얻을 수 있습니다. http://svn.python.org/projects/python/trunk/Misc/gdbinit를 에 넣고 ~/.gdbinit다음을 수행하십시오.

  • gdb 첨부 : gdb -p PID
  • 파이썬 스택 추적을 가져옵니다. pystack

불행히도 완전히 신뢰할 만하지는 않지만 대부분의 경우 작동합니다.

마지막으로, 첨부 strace는 프로세스가 수행하는 작업에 대한 좋은 아이디어를 제공 할 수 있습니다.


답변

나는 거의 항상 여러 스레드를 다루고 있으며 주요 스레드는 일반적으로 많은 일을하지 않으므로 가장 흥미로운 것은 모든 스택을 덤프하는 것입니다 (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의 팁은 다른 도구 중에서도 이에 대한 포인터가 포함되어 있습니다.)


답변

>>> 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()


답변

결함 핸들러 모듈을 시도 할 수 있습니다 . 다음을 사용하여 설치 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/를 참조 하십시오.