예외가 발생할 때 Python 추적 객체를 어떻게 수정할 수 있나요?

StackOverflow https://stackoverflow.com/questions/1603940

  •  05-07-2019
  •  | 
  •  

문제

저는 타사 개발자가 핵심 애플리케이션에 대한 확장을 작성하는 데 사용하는 Python 라이브러리를 작업하고 있습니다.

예외가 발생할 때 역추적을 수정할 수 있는지 알고 싶습니다. 따라서 마지막 스택 프레임은 예외를 발생시킨 라이브러리의 줄이 아니라 개발자 코드의 라이브러리 함수에 대한 호출입니다.또한 이상적으로 제거하고 싶은 코드를 처음 로드할 때 사용되는 함수에 대한 참조가 포함된 스택 맨 아래에 몇 개의 프레임이 있습니다.

어떤 조언이라도 미리 감사드립니다!

도움이 되었습니까?

해결책

추적을 바꾸지 않는 것은 어떻습니까? 당신이 요청한 두 가지는 둘 다 다른 방식으로 더 쉽게 수행 할 수 있습니다.

  1. 도서관의 예외가 개발자의 코드에 잡히고 대신 새로운 예외가 제기되면 원래 추적 백이 물론 던져집니다. 이것은 예외가 일반적으로 처리되는 방법입니다 ... 원래 예외를 제기 할 수 있지만 모든 "상위"프레임을 제거하기 위해 멍청한 경우 트레이스 백의 마지막 줄은 그렇지 않기 때문에 실제 예외는 의미가 없습니다. 그 자체는 예외를 제기 할 수 있습니다.
  2. 마지막 몇 프레임을 제거하려면 TraceBack.print_exception ()과 같은 것들이 마지막 몇 항목을 건너 뛰는 데 사용할 수있는 "제한"매개 변수를 취하도록 요청할 수 있습니다.

즉, 정말로 필요하다면 트레이스 백을 munge 할 수 있어야합니다 ... 그러나 어디에서 할 수 있습니까? 최상위 레벨의 일부 래퍼 코드에서 트레이스 백을 잡고 슬라이스를 가져 와서 원하지 않는 부분을 제거한 다음 "트레이스 백"모듈에서 함수를 사용하여 원하는대로 포맷/인쇄 할 수 있습니다.

다른 팁

TRACEBACK의 TB_NEXT 요소로 올리면 트레이스 백 상단을 쉽게 제거 할 수 있습니다.

except:
    ei = sys.exc_info()
    raise ei[0], ei[1], ei[2].tb_next

tb_next는 read_only 속성이므로 바닥에서 물건을 제거하는 방법을 모릅니다. 속성에 액세스 할 수 있도록 속성 메커니즘을 망칠 수 있지만 어떻게 해야하는지 모르겠습니다.

Jinja2가 여기에서 무엇을하는지 살펴보십시오.

https://github.com/mitsuhiko/jinja2/blob/5b498453b5898257b287f14ef6c363799f1405a/jinja2/debug.py

못 생겼지 만 필요한 일을하는 것 같습니다. 예제가 길기 때문에 여기서 예를 복사하지 않습니다.

당신은 또한에 관심이있을 수 있습니다 PEP-3134, Python 3에서 구현되었으며 하나의 예외/추적을 업스트림 예외에 추가할 수 있습니다.

이는 역추적을 수정하는 것과 완전히 동일한 것은 아니지만, "긴 버전"을 계속 사용하면서 라이브러리 사용자에게 "짧은 버전"을 전달하는 이상적인 방법일 것입니다.

이 코드는 귀하에게 관심이있을 수 있습니다.

추적이 필요하고 첫 번째 파일을 제거하여 표시되지 않아야합니다. 그런 다음 파이썬 동작을 시뮬레이션합니다.

Traceback (most recent call last):

트레이스 백에 둘 이상의 파일이 포함 된 경우에만 표시됩니다. 이것은 내 여분의 프레임이없는 것처럼 보입니다.

여기 내 코드가 문자열이 있다고 가정합니다 text:

try:
    exec(text)
except:
    # we want to format the exception as if no frame was on top.
    exp, val, tb = sys.exc_info()
    listing = traceback.format_exception(exp, val, tb)
    # remove the entry for the first frame
    del listing[1]
    files = [line for line in listing if line.startswith("  File")]
    if len(files) == 1:
        # only one file, remove the header.
        del listing[0]
    print("".join(listing), file=sys.stderr)
    sys.exit(1)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top