[python] 파이썬 : 어떤 유형의 예외가 발생했는지 어떻게 알 수 있습니까?

메인 프로그램에서 호출 한 함수가 있습니다 :

try:
    someFunction()
except:
    print "exception happened!"

그러나 함수 실행 중에 예외가 발생하므로 해당 except부분으로 이동합니다 .

someFunction()예외가 발생한 원인을 정확히 어떻게 알 수 있습니까?



답변

다른 답변은 일반적인 예외를 잡아서는 안된다고 지적하지만 아무도 규칙을 어길 수있는 시점을 이해하는 데 필수적인 이유를 말하고 싶지 않습니다. 여기 에 설명이 있습니다. 기본적으로 숨기지 않습니다.

따라서 이러한 작업을 수행하지 않는 한 일반적인 예외를 잡는 것이 좋습니다. 예를 들어 다음과 같은 다른 방법으로 예외에 대한 정보를 사용자에게 제공 할 수 있습니다.

  • GUI에서 대화 상자로 예외 표시
  • 멀티 스레딩 또는 멀티 프로세싱 응용 프로그램에서 작업자 스레드 또는 프로세스에서 제어 스레드 또는 프로세스로 예외 전송

그렇다면 일반적인 예외를 잡는 방법은 무엇입니까? 몇 가지 방법이 있습니다. 예외 객체를 원한다면 다음과 같이하십시오.

try:
    someFunction()
except Exception as ex:
    template = "An exception of type {0} occurred. Arguments:\n{1!r}"
    message = template.format(type(ex).__name__, ex.args)
    print message

놓칠 수없는 방식으로 사용자의주의를 끌 도록 하십시오 message ! 위와 같이 메시지가 다른 많은 메시지에 묻혀 있으면 인쇄하기에 충분하지 않을 수 있습니다. 사용자의 관심을 끌지 못하는 것은 모든 예외를 삼키는 데 큰 영향을 미치며,이 페이지의 답변을 읽은 후 사라져야 할 인상이 있다면 이것이 좋지 않은 것 입니다. 를 사용하여 except 블록 끝내기raisestatement로 발견 된 예외를 투명하게 다시 발생시켜 문제를 해결할 수 있습니다.

위와 except:인수없이 그냥 사용하는 것의 차이점 은 두 가지입니다.

  • 베어 except:는 검사 할 예외 개체를 제공하지 않습니다.
  • 예외는 SystemExit, KeyboardInterrupt그리고 GeneratorExit일반적으로 당신이 원하는 무엇을 위의 코드에 의해 잡힌되지 않습니다. 예외 계층을 참조하십시오 .

예외를 잡지 않으면 동일한 스택 추적을 원한다면 다음과 같이 얻을 수 있습니다 (여전히 except 절 안에 있음).

import traceback
print traceback.format_exc()

logging모듈 을 사용하는 경우 다음과 같이 예외를 메시지와 함께 로그에 인쇄 할 수 있습니다.

import logging
log = logging.getLogger()
log.exception("Message for you, sir!")

더 깊이 파고 스택을 검사하려면 변수 등을 살펴보고 except 블록 내부의 모듈 post_mortem기능을 사용하십시오 pdb.

import pdb
pdb.post_mortem()

나는이 마지막 방법이 버그를 사냥 할 때 귀중한 것으로 나타났습니다.


답변

예외 개체가 속한 클래스의 이름을 가져옵니다.

e.__class__.__name__

print_exc () 함수를 사용하면 모든 오류 메시지에 대한 필수 정보 인 스택 추적을 인쇄합니다.

이처럼 :

from traceback import print_exc

class CustomException(Exception): pass

try:
    raise CustomException("hi")
except Exception, e:
    print 'type is:', e.__class__.__name__
    print_exc()
    # print "exception happened!"

다음과 같이 출력됩니다 :

type is: CustomException
Traceback (most recent call last):
  File "exc.py", line 7, in <module>
    raise CustomException("hi")
CustomException: hi

그리고 인쇄 및 분석 후 코드는 예외를 처리하지 않고 다음을 실행하기로 결정할 수 있습니다 raise.

from traceback import print_exc

class CustomException(Exception): pass

def calculate():
    raise CustomException("hi")

try:
    calculate()
except Exception, e:
    if e.__class__ == CustomException:
        print 'special case of', e.__class__.__name__, 'not interfering'
        raise
    print "handling exception"

산출:

special case of CustomException not interfering

그리고 인터프리터는 예외를 인쇄합니다.

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    calculate()
  File "test.py", line 6, in calculate
    raise CustomException("hi")
__main__.CustomException: hi

raise원래 예외 후에 계속해서 호출 스택을 계속 전파합니다. ( 가능한 함정에주의하십시오 ) 새로운 예외를 제기하면 새로운 (더 짧은) 스택 추적이 필요합니다.

from traceback import print_exc

class CustomException(Exception): pass

def calculate():
    raise CustomException("hi")

try:
    calculate()
except Exception, e:
    if e.__class__ == CustomException:
        print 'special case of', e.__class__.__name__, 'not interfering'
        #raise CustomException(e.message)
        raise e
    print "handling exception"

산출:

special case of CustomException not interfering
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    raise CustomException(e.message)
__main__.CustomException: hi    

역 추적 에 원래 예외의 원점 인 calculate()line 함수가 포함되지 않은 방법에 주목하십시오 .9e


답변

일반적으로 예외 try: ... except가 너무 광범위하므로 가능한 모든 예외를 포착해서는 안됩니다 . 어떤 이유로 든 일어날 것으로 예상되는 것들을 잡아라. 예를 들어 디버깅하는 동안 일부 문제에 대해 더 자세히 알고 싶다면 실제로해야합니다.

try:
    ...
except Exception as ex:
    print ex # do whatever you want for debugging.
    raise    # re-raise exception.


답변

somefunction코딩 된 레거시 기능이 매우 나쁜 경우 가 아니라면 원하는 것을 요구하지 않아도됩니다.

여러 except절을 사용 하여 다른 예외를 다른 방식으로 처리 하십시오 .

try:
    someFunction()
except ValueError:
    # do something
except ZeroDivision:
    # do something else

요점은 일반적인 예외를 잡아서는 안되며 필요한 예외 만 잡아야한다는 것입니다. 예기치 않은 오류나 버그를 숨기고 싶지 않다고 확신합니다.


답변

대부분의 대답은 except (…) as (…):구문을 가리키고 있지만 (정확히), 동시에 코끼리가 sys.exc_info()기능 하는 방에있는 코끼리에 대해 이야기하고 싶은 사람은 없습니다 . sys 모듈 (강조 광산) 의 문서 에서 :

이 함수는 현재 처리중인 예외에 대한 정보를 제공하는 세 가지 값의 튜플을 반환합니다.
(…)
스택의 어느 곳에서나 예외가 처리되지 않으면 3 개의 None 값을 포함하는 튜플이 반환됩니다. 그렇지 않으면 리턴 된 값은 (type, value, traceback)입니다. 의미는 다음과 같습니다. type은 처리중인 예외 유형 (BaseException의 서브 클래스)을 가져옵니다 . value는 예외 인스턴스 (예외 유형의 인스턴스)를 가져옵니다. traceback은 예외가 원래 발생한 지점에서 콜 스택을 캡슐화하는 traceback 객체를 가져옵니다 (참조 매뉴얼 참조).

어떤 유형의 예외가 발생했는지 어떻게 알 수 있습니까?sys.exc_info() 의 원래 질문에 대한 가장 직접적인 대답으로 간주 될 수 있다고 생각합니다 .


답변

시도 : 예외를 제외하고 someFunction ()

#this is how you get the type
excType = exc.__class__.__name__

#here we are printing out information about the Exception
print 'exception type', excType
print 'exception msg', str(exc)

#It's easy to reraise an exception with more information added to it
msg = 'there was a problem with someFunction'
raise Exception(msg + 'because of %s: %s' % (excType, exc))


답변

이 답변은 디버깅에는 적합하지만 프로그래밍 방식으로 예외를 테스트하는 경우 isinstance(e, SomeException)하위 클래스 SomeException도 테스트하므로 편리 하므로 예외 계층에 적용되는 기능을 만들 수 있습니다.