오류가 발생하면 자동으로 파이썬 디버거 시작


216

이것은 내가 오랫동안 궁금해 한 질문이지만 적절한 해결책을 찾지 못했습니다. 스크립트를 실행하고 IndexError라고 가정하면 Python은 오류의 줄, 위치 및 빠른 설명을 인쇄하고 종료합니다. 오류가 발생하면 pdb를 자동으로 시작할 수 있습니까? 파일 맨 위에 여분의 import 문을 사용하거나 몇 줄의 추가 코드를 작성하는 것에 반대하지 않습니다.


12
허용되는 답변 변경을 고려 했습니까?
Joost

답변:


127

traceback.print_exc 를 사용 하여 예외 추적을 인쇄 할 수 있습니다 . 그런 다음 sys.exc_info 를 사용하여 추적을 추출하고 마지막 으로 해당 추적으로 pdb.post_mortem 을 호출 하십시오.

import pdb, traceback, sys

def bombs():
    a = []
    print a[0]

if __name__ == '__main__':
    try:
        bombs()
    except:
        extype, value, tb = sys.exc_info()
        traceback.print_exc()
        pdb.post_mortem(tb)

예외가 발생한 프레임의 로컬을 사용하여 code.interact 로 대화식 명령 행을 시작하려는 경우 수행 할 수 있습니다.

import traceback, sys, code

def bombs():
    a = []
    print a[0]

if __name__ == '__main__':
    try:
        bombs()
    except:
        type, value, tb = sys.exc_info()
        traceback.print_exc()
        last_frame = lambda tb=tb: last_frame(tb.tb_next) if tb.tb_next else tb
        frame = last_frame().tb_frame
        ns = dict(frame.f_globals)
        ns.update(frame.f_locals)
        code.interact(local=ns)

첫 번째 해결책은 파이썬 요리 책
dirkjot

3
후자가 전자 code보다 pdb확대되는 것처럼 보이기 때문에 왜 누군가가 선호 하는가?
K3 --- rnc

나는 같은 질문이 있습니까? 왜 선호 code합니까?
ARH

2
그런 다음을 사용 sys.exc_info하여 추적을 추출하고 마지막 pdb.post_mortem으로 해당 추적을 호출하십시오 . 에 traceback 객체를 전달할 필요가 없습니다 pdb.post_mortem. 에서 문서 : 더 추적을 지정하지 않으면, 그것은 현재 (기본값은 사용하는 경우 예외가 처리되지해야 함) 처리되고있는 예외의 하나를 사용합니다.
Piotr Dobrogost

2
@PiotrDobrogost 좋은 지적입니다. API를 더 잘 보여주기 때문에 tb 객체를 전달할 수 있다는 것을 아는 것이 더 도움이된다고 생각합니다. 두 가지 옵션이 모두 있음을 아는 것이 좋습니다.
davidA

454
python -m pdb -c continue myscript.py

-c continue플래그를 제공하지 않으면 실행이 시작될 때 '계속'에 'c'를 입력해야합니다. 그런 다음 오류 지점까지 실행되어 제어 할 수 있습니다. 마찬가지로 eqzx 언급 입력 'C'가 이전 버전 파이썬 (참조 필요하므로,이 플래그 파이썬 3.2 새로운 추가는 https://docs.python.org/3/library/pdb.html을 ).


5
" Enter 'c "를 언급 해주셔서 감사합니다. 일반적으로'r '( "run")을 입력했습니다 gdb. 에 'r'을 입력하면 pdb프로그램은 실제로 실행되지만 오류가 발생하면 중지하지 않습니다 (역 추적을 생성하지 않습니다). 내가 이것을 읽을 때까지 당황했다. 건배!
sdaau

3
Vineet, 디버거를 켜고 시작하므로 "cont"를 입력하면 오류가 발생할 때까지 실행됩니다. 거기에서 다른 pdb 세션과 같이 변수 등을 검사 할 수 있습니다.
Catherine Devlin

40
OP, 답변으로 동의하십시오. 이것은 가장 유용하며이 것을 칠 때까지 다른 것들을 읽는 데 5 분을 낭비했습니다.
jhegedus

4
이것도 마찬가지입니다 ipdb; 물론 스크립트 뒤에 인수를 추가 할 수 있습니다!
tutuDajuju

20
Python 2.7에서는 작동하지 않습니다. docs.python.org/3/library/pdb.html : "버전 3.2의 새로운 기능 : pdb.py는 이제 명령을 실행하는 -c 옵션을 허용합니다"
eqzx

68

다음 모듈을 사용하십시오.

import sys

def info(type, value, tb):
    if hasattr(sys, 'ps1') or not sys.stderr.isatty():
    # we are in interactive mode or we don't have a tty-like
    # device, so we call the default hook
        sys.__excepthook__(type, value, tb)
    else:
        import traceback, pdb
        # we are NOT in interactive mode, print the exception...
        traceback.print_exception(type, value, tb)
        print
        # ...then start the debugger in post-mortem mode.
        # pdb.pm() # deprecated
        pdb.post_mortem(tb) # more "modern"

sys.excepthook = info

이름 debug(또는 원하는대로)을 파이썬 경로의 어딘가에 넣으십시오.

이제 스크립트 시작시을 추가하십시오 import debug.


2
이것은 받아 들일만한 대답이어야합니다. 기존 코드를 수정하거나 try-catch추한 IMO 인 모든 것을 래핑하지 않아도 됩니다.
cyphar

나는이 대답을 다소 자주 좋아하지만 선호 pudb합니다 pdb. 내 삶의 질서 부족에 대해 분명히 말하는 복사하여 붙여 넣기로 계속 돌아가십시오.
Stabledog December

47

Ipython 에는이 동작을 전환하는 명령이 있습니다 : % pdb . 그것은 당신이 묘사 한 것과 똑같이 더 잘 할 것입니다 (구문 강조 및 코드 완성으로 더 유익한 백 트레이스를 제공합니다). 시도해 볼만한 가치가 있습니다!


3
그리고 이것에 대한 유일한 합리적인 답변입니다.
Michael


4
docs @matthiash 링크에서 언급했듯이 오류가 발생한 %debug 디버거를 열 수 있습니다 . 나는 종종 이것보다 선호한다 . (절충는 단지 입력됩니다 당신이 입력 오류 대를 디버깅하지 않으려 할 때마다 매번 할이 오류를 디버깅 할합니다.)%pdbq%debug
브라만 스나이더

1
자신의 설정 c.InteractiveShell.pdb = True은 모든 세션 ipython_config.py에 대해 %pdb자동으로 켜집니다 .
Braham Snyder

33

이것은 디버거가 아니지만 아마도 유용 할 것입니다 (?)

귀도가이 연설을 어딘가에서 들었다고 들었습니다.

방금 python-?를 확인했으며 -i 명령을 사용하면 스크립트가 중지 된 위치에서 상호 작용할 수 있습니다.

따라서이 스크립트가 주어지면 :

testlist = [1,2,3,4,5, 0]

prev_i = None
for i in testlist:
    if not prev_i:
        prev_i = i
    else:
        result = prev_i/i

이 결과를 얻을 수 있습니다!

PS D:\> python -i debugtest.py
Traceback (most recent call last):
  File "debugtest.py", line 10, in <module>
    result = prev_i/i
ZeroDivisionError: integer division or modulo by zero
>>>
>>>
>>> prev_i
1
>>> i
0
>>>

솔직히 말해서 나는 이것을 사용하지 않았지만 매우 유용합니다.



8
그다지 유용하지는 않지만 글로벌 범위로 진출합니다. 어떤 기능이 충돌하더라도 찌를 수 없습니다.
pixelpax

21

IPython은 명령 행에서 이것을 간단하게 만듭니다.

python myscript.py arg1 arg2

다시 쓸 수있다

ipython --pdb myscript.py -- arg1 arg2

또는 마찬가지로 모듈을 호출하는 경우 :

python -m mymodule arg1 arg2

다시 쓸 수있다

ipython --pdb -m mymodule -- arg1 arg2

--IPython이 스크립트의 인수를 독자적으로 읽지 못하게하려면를 참고하십시오 .

또한 pdb 대신 고급 IPython 디버거 (ipdb)를 호출 할 수 있다는 장점이 있습니다.


10

를 사용하는 경우 ipython유형을 시작한 후%pdb

In [1]: %pdb
Automatic pdb calling has been turned ON

예를 들어
Jupyter

6

IPython 환경을 사용하는 경우 % debug를 사용할 수 있으며 쉘은 검사 등을 위해 ipdb 환경의 문제를 일으키는 라인으로 되돌아갑니다. 위에서 지적한 다른 옵션은 효과적으로 iPython 매직 % pdb를 사용하는 것입니다 똑같다.


오류가 모듈 기능에서 발생한 경우, 당신이 가진 프레임을 탐색 할 수 있습니다 updown명령은 오류를 생성 한 것을 코드의 라인으로 돌아갑니다.
Jean Paul


3

처음에 c를 입력하지 않고 실행하려면 다음을 사용하십시오.

python -m pdb -c c <script name>

Pdb는 자체 명령 행 인수를 갖습니다. -cc는 실행 시작시 c (ontinue) 명령을 실행하고 오류가 발생할 때까지 프로그램이 중단없이 실행됩니다.


3

python2.7-python2.7의 python -m pdb script.py는 계속해서 시작되며 오류가 발생하여 디버그를 위해 중단됩니다.


1

모듈을 실행중인 경우 :

python -m mymodule

이제 pdb예외가 발생했을 때 입력하고 싶습니다 .

PYTHONPATH="." python -m pdb -c c mymodule/__main__.py

(또는 확장 당신을 PYTHONPATH). 는 PYTHONPATH모듈이 경로에서 찾을 수 있도록 실행되기 때문에, 필요한 pdb지금 모듈을.


0

계층 구조에서 최상위 예외 클래스의 생성자 안에 중단 점을 두십시오. 대부분의 경우 오류가 발생한 위치를 보게됩니다.

당신이 의미하는 원하는 중단 점 수단 퍼팅 : 당신은 IDE를 사용하거나 pdb.set_trace, 또는 무엇이든

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.