파이썬의 "내부 예외"(트레이스백 포함)?
제 경력은 C#이고 최근에 Python에서 프로그래밍을 시작했습니다.예외가 발생할 경우 일반적으로 전체 스택 추적을 표시하면서 추가 정보를 추가하는 다른 예외로 래핑합니다.C#에서는 꽤 쉽지만, Python에서는 어떻게 해야 합니까?
예: C#에서 다음과 같은 작업을 수행합니다.
try
{
ProcessFile(filePath);
}
catch (Exception ex)
{
throw new ApplicationException("Failed to process file " + filePath, ex);
}
Python에서도 비슷한 작업을 수행할 수 있습니다.
try:
ProcessFile(filePath)
except Exception as e:
raise Exception('Failed to process file ' + filePath, e)
...하지만 이것은 내부 예외의 흔적을 잃어버립니다!
편집: 예외 메시지와 스택 추적을 모두 보고 두 개의 상관 관계를 알고 싶습니다.즉, 출력에서 예외 X가 여기서 발생한 다음 예외 Y가 여기서 발생한 것을 확인하고 싶습니다. - C#에서와 동일합니다.이것이 파이썬 2.6에서 가능합니까?제가 지금까지 할 수 있는 최선의 방법은 다음과 같습니다(Glenn Maynard의 답변 기준).
try:
ProcessFile(filePath)
except Exception as e:
raise Exception('Failed to process file' + filePath, e), None, sys.exc_info()[2]
여기에는 메시지와 추적백이 모두 포함되지만 추적백에서 발생한 예외는 표시되지 않습니다.
파이썬 3
python 3에서 다음을 수행할 수 있습니다.
try:
raise MyExceptionToBeWrapped("I have twisted my ankle")
except MyExceptionToBeWrapped as e:
raise MyWrapperException("I'm not in a good shape") from e
이는 다음과 같은 결과를 초래합니다.
Traceback (most recent call last):
...
MyExceptionToBeWrapped: ("I have twisted my ankle")
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
...
MyWrapperException: ("I'm not in a good shape")
파이썬 2
이것은 간단합니다. 세 번째 주장으로 추적을 되돌립니다.
import sys
class MyException(Exception): pass
try:
raise TypeError("test")
except TypeError, e:
raise MyException(), None, sys.exc_info()[2]
하나의 예외를 포착하고 다른 예외를 다시 발생시킬 때는 항상 이 작업을 수행합니다.
Python 3에는 체인 예외에 대한 ... 절이 있습니다.글렌의 답변은 Python 2.7에 유용하지만 원래 예외의 추적만 사용하고 오류 메시지 및 기타 세부 정보는 무시합니다.다음은 Python 2.7에서 현재 범위의 컨텍스트 정보를 원래 예외의 오류 메시지에 추가하지만 다른 세부 정보는 그대로 유지하는 몇 가지 예입니다.
알려진 예외 유형
try:
sock_common = xmlrpclib.ServerProxy(rpc_url+'/common')
self.user_id = sock_common.login(self.dbname, username, self.pwd)
except IOError:
_, ex, traceback = sys.exc_info()
message = "Connecting to '%s': %s." % (config['connection'],
ex.strerror)
raise IOError, (ex.errno, message), traceback
이러한 특성의 문은 예외 유형을 첫 번째 식으로, 예외 클래스 생성자 인수를 두 번째 식으로, 추적백을 세 번째 식으로 사용합니다.Python 2.2 이전 버전을 실행 중인 경우 의 경고를 참조하십시오.
모든 예외 유형
코드에서 어떤 종류의 예외를 인식해야 할지 모르는 경우 일반적인 용도로 사용할 수 있는 다른 예가 있습니다.단점은 예외 유형이 손실되고 런타임 오류만 발생한다는 것입니다.은 다항목가합니다야와져음을 해야 합니다.traceback
모듈.
except Exception:
extype, ex, tb = sys.exc_info()
formatted = traceback.format_exception_only(extype, ex)[-1]
message = "Importing row %d, %s" % (rownum, formatted)
raise RuntimeError, message, tb
메시지 수정
예외 유형을 사용하여 컨텍스트를 추가할 수 있는 경우 다음과 같은 옵션이 있습니다.예외 메시지를 수정한 후 다시 올릴 수 있습니다.
import subprocess
try:
final_args = ['lsx', '/home']
s = subprocess.check_output(final_args)
except OSError as ex:
ex.strerror += ' for command {}'.format(final_args)
raise
그러면 다음 스택 추적이 생성됩니다.
Traceback (most recent call last):
File "/mnt/data/don/workspace/scratch/scratch.py", line 5, in <module>
s = subprocess.check_output(final_args)
File "/usr/lib/python2.7/subprocess.py", line 566, in check_output
process = Popen(stdout=PIPE, *popenargs, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1327, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory for command ['lsx', '/home']
당신은 그것이 다음의 선을 보여주는 것을 볼 수 있습니다.check_output()
호출되었지만 이제 예외 메시지에 명령줄이 포함됩니다.
Python 3.x의 경우:
raise Exception('Failed to process file ' + filePath).with_traceback(e.__traceback__)
아니면 간단히
except Exception:
raise MyException()
그것은 전파될 것입니다.MyException
처리되지 않을 경우 두 예외를 모두 인쇄합니다.
Python 2.x의 경우:
raise Exception, 'Failed to process file ' + filePath, e
두 예외를 모두 인쇄하지 않도록 하려면 다음과 같이 하십시오.__context__
기여하다.여기서 예외를 즉시 파악하고 변경하기 위해 컨텍스트 관리자를 작성합니다(작동 방식에 대한 자세한 내용은 http://docs.python.org/3.1/library/stdtypes.html 참조).
try: # Wrap the whole program into the block that will kill __context__.
class Catcher(Exception):
'''This context manager reraises an exception under a different name.'''
def __init__(self, name):
super().__init__('Failed to process code in {!r}'.format(name))
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None:
self.__traceback__ = exc_tb
raise self
...
with Catcher('class definition'):
class a:
def spam(self):
# not really pass, but you get the idea
pass
lut = [1,
3,
17,
[12,34],
5,
_spam]
assert a().lut[-1] == a.spam
...
except Catcher as e:
e.__context__ = None
raise
Python 2.x에서는 이것을 할 수 없다고 생각하지만, 이 기능과 비슷한 것이 Python 3의 일부입니다.PEP 3134에서:
오늘날의 Python 구현에서 예외는 유형, 값 및 추적백의 세 부분으로 구성됩니다.'sys' 모듈은 exc_type, exc_value 및 exc_traceback이라는 세 개의 병렬 변수에 현재 예외를 노출하고, sys.exc_info() 함수는 이 세 부분 중 튜플을 반환하며, 'raise' 문은 이 세 부분을 수락하는 세 개의 인수 형식을 가집니다.예외를 조작하려면 이 세 가지를 병렬로 전달해야 하는 경우가 많은데, 이는 지루하고 오류가 발생하기 쉽습니다.또한 'except' 문은 값에 대한 액세스만 제공할 수 있고 추적은 제공할 수 없습니다.예외 값에 '추적' 특성을 추가하면 단일 위치에서 모든 예외 정보에 액세스할 수 있습니다.
C#과 비교:
C#의 예외에는 다른 예외를 나타낼 수 있는 읽기 전용 'InnerException' 속성이 포함되어 있습니다.문서 [10]에는 "예외 X가 이전 예외 Y의 직접적인 결과로 던져질 때 X의 InnerException 속성은 Y에 대한 참조를 포함해야 합니다."라고 나와 있습니다.이 속성은 VM에 의해 자동으로 설정되지 않으며, 모든 예외 생성자는 선택적인 'innerException' 인수를 사용하여 명시적으로 설정합니다.cause' 속성은 InnerException과 동일한 목적을 달성하지만 이 PEP는 모든 예외의 생성자를 확장하는 것이 아니라 새로운 형태의 '상승'을 제안합니다.C#은 또한 GetBase를 제공합니다.InnerException 체인의 끝으로 바로 이동하는 예외 메서드입니다. 이 PEP는 아날로그를 제안하지 않습니다.
또한 Java, Ruby 및 Perl 5도 이러한 유형의 작업을 지원하지 않습니다.다시 인용하기:
다른 언어의 경우, Java와 Ruby 모두 'catch'/'rescue' 또는 'finally'/'sure' 절에 다른 예외가 발생할 때 원래 예외를 삭제합니다.Perl 5에는 구조화된 예외 처리 기능이 내장되어 있지 않습니다.Perl 6의 경우, RFC 번호 88[9]은 @@@라는 이름의 배열에 연결된 예외를 암시적으로 유지하는 예외 메커니즘을 제안합니다.
Python 2와 3 간의 최대 호환성을 위해 다음을 사용할 수 있습니다.raise_from
에서six
도서관.https://six.readthedocs.io/ #6.dll_from.다음은 예입니다(명확하게 하기 위해 약간 수정됨).
import six
try:
ProcessFile(filePath)
except Exception as e:
six.raise_from(IOError('Failed to process file ' + repr(filePath)), e)
내 CauseException 클래스를 사용하여 Python 2.x에서 예외를 체인화할 수 있습니다(그리고 Python 3에서도 새로 발생한 예외의 원인으로 둘 이상의 탐지된 예외를 제공하려는 경우 유용할 수 있습니다).도움이 될 수도 있어요
관련 정보를 수집하여 전달해 주시겠습니까?저는 다음과 같은 생각을 합니다.
import traceback
import sys
import StringIO
class ApplicationError:
def __init__(self, value, e):
s = StringIO.StringIO()
traceback.print_exc(file=s)
self.value = (value, s.getvalue())
def __str__(self):
return repr(self.value)
try:
try:
a = 1/0
except Exception, e:
raise ApplicationError("Failed to process file", e)
except Exception, e:
print e
가정:
- Python 2(순수한 Python 3의 경우)에서 작동하는 솔루션이 필요합니다.
raise ... from
솔루션) - 오류 메시지를 강화하고 싶을 뿐입니다. 예를 들어 추가 컨텍스트를 제공
- 전체 스택 추적이 필요합니다.
다음 문서에서 간단한 솔루션을 사용할 수 있습니다. https://docs.python.org/3/tutorial/errors.html#raising-exceptions :
try:
raise NameError('HiThere')
except NameError:
print 'An exception flew by!' # print or log, provide details about context
raise # reraise the original exception, keeping full stack trace
출력:
An exception flew by!
Traceback (most recent call last):
File "<stdin>", line 2, in ?
NameError: HiThere
핵심 요소는 단독으로 서 있는 단순화된 '상승' 키워드인 것으로 보입니다.그러면 예외 블록에서 예외가 다시 발생합니다.
언급URL : https://stackoverflow.com/questions/1350671/inner-exception-with-traceback-in-python
'programing' 카테고리의 다른 글
신뢰할 수 있는 Excel 범위 구문 참조 (0) | 2023.07.05 |
---|---|
Python에서 문자열 형식 지정에 여러 인수 사용(예: '%s... %s') (0) | 2023.07.05 |
Spring Boot 로깅에 사용되는 기본 CONSOLE_LOG_PATTERN은 무엇이며 어디에서 찾을 수 있습니까? (0) | 2023.07.05 |
스프링 부트에서 최대 절전 모드 유형-52를 사용할 때 하이퍼리스틱스 배너를 비활성화하는 방법은 무엇입니까? (0) | 2023.06.30 |
VBA 매크로를 사용하여 Excel 시트 이름 바꾸기 (0) | 2023.06.30 |