"traceback" --- 스택 트레이스백 인쇄와 조회
*******************************************

**소스 코드:** Lib/traceback.py

======================================================================

이 모듈은 파이썬 프로그램의 스택 트레이스를 추출, 포맷 및 인쇄하는 표
준 인터페이스를 제공합니다. 스택 트레이스를 인쇄할 때 파이썬 인터프리
터의 동작을 정확하게 모방합니다. 이것은 가령 인터프리터를 둘러싸는 "래
퍼"처럼 프로그램 제어 하에서 스택 트레이스를 인쇄하려고 할 때 유용합니
다.

이 모듈은 트레이스백 객체를 사용합니다 --- 이는 "sys.last_traceback"
변수에 저장되고 "sys.exc_info()"의 세 번째 항목으로 반환되는 객체 형입
니다.

이 모듈은 다음 함수를 정의합니다:

traceback.print_tb(tb, limit=None, file=None)

   *limit*가 양수면 (호출자 프레임에서 시작하여) 트레이스백 객체 *tb*
   의 최대 *limit* 개의 스택 트레이스 항목을 인쇄합니다. 그렇지 않으면
   , 마지막 "abs(limit)" 항목을 인쇄합니다. *limit*가 생략되거나
   "None"이면, 모든 항목이 인쇄됩니다. *file*이 생략되거나 "None"이면,
   출력은 "sys.stderr"로 갑니다; 그렇지 않으면 출력을 받을 열린 파일이
   나 파일류 객체여야 합니다.

   버전 3.5에서 변경: 음수 *limit* 지원을 추가했습니다.

traceback.print_exception(etype, value, tb, limit=None, file=None, chain=True)

   예외 정보와 트레이스백 객체 *tb*의 스택 트레이스 항목을 *file*로 인
   쇄합니다. 이것은 다음과 같은 점에서 "print_tb()"와 다릅니다:

   * *tb*가 "None"이 아니면, 헤더 "Traceback (most recent call last):"
     를 인쇄합니다.

   * 스택 트레이스 다음에 예외 *etype*과 *value*를 인쇄합니다.

   * *type(value)*가 "SyntaxError"고 *value*가 적절한 형식을 가지면,
     에러의 대략적인 위치를 나타내는 캐럿(caret)과 함께 문법 에러가 발
     생한 줄을 인쇄합니다.

   선택적 *limit* 인자는 "print_tb()"와 같은 의미입니다. *chain*이 참(
   기본값)이면, 처리되지 않은 예외를 인쇄할 때 인터프리터 자체가 하는
   것과 마찬가지로, 연결된 예외(예외의 "__cause__"나 "__context__" 어
   트리뷰트)도 인쇄됩니다.

   버전 3.5에서 변경: *etype* 인자는 무시되고 *value* 형에서 유추됩니
   다.

traceback.print_exc(limit=None, file=None, chain=True)

   이것은 "print_exception(*sys.exc_info(), limit, file, chain)"의 줄
   임 표현입니다.

traceback.print_last(limit=None, file=None, chain=True)

   이것은 "print_exception(sys.last_type, sys.last_value,
   sys.last_traceback, limit, file, chain)"의 줄임 표현입니다. 일반적
   으로 예외가 대화식 프롬프트에 도달한 후에만 작동합니다
   ("sys.last_type"을 참조하십시오).

traceback.print_stack(f=None, limit=None, file=None)

   *limit*가 양수면 (호출 지점에서 시작하여) 최대 *limit* 개의 스택 트
   레이스 항목을 인쇄합니다. 그렇지 않으면, 마지막 "abs(limit)" 항목을
   인쇄합니다. *limit*가 생략되거나 "None"이면, 모든 항목이 인쇄됩니다
   . 선택적 *f* 인자를 사용하여 시작할 대체 스택 프레임을 지정할 수 있
   습니다. 선택적 *file* 인자는 "print_tb()"와 같은 의미입니다.

   버전 3.5에서 변경: 음수 *limit* 지원을 추가했습니다.

traceback.extract_tb(tb, limit=None)

   트레이스백 객체 *tb*에서 추출된 "전 처리된" 스택 트레이스 항목의 리
   스트를 나타내는 "StackSummary" 객체를 반환합니다. 스택 트레이스의
   대체 포매팅으로 유용합니다. 선택적 *limit* 인자는 "print_tb()"와 같
   은 의미입니다. "전 처리된" 스택 트레이스 항목은 일반적으로 스택 트
   레이스를 위해 인쇄되는 정보를 나타내는 어트리뷰트 "filename",
   "lineno", "name" 및 "line"을 포함하는 "FrameSummary" 객체입니다.
   "line"은 선행과 후행 공백이 제거된 문자열입니다; 소스를 사용할 수
   없으면 "None"입니다.

traceback.extract_stack(f=None, limit=None)

   현재 스택 프레임에서 날 트레이스백을 추출합니다. 반환 값은
   "extract_tb()"와 같은 형식입니다. 선택적 *f*와 *limit* 인자는
   "print_stack()"과 같은 의미입니다.

traceback.format_list(extracted_list)

   "extract_tb()"나 "extract_stack()"이 반환한 튜플이나 "FrameSummary"
   객체의 리스트가 제공되면, 인쇄할 준비가 된 문자열의 리스트를 반환합
   니다. 결과 리스트의 각 문자열은 인자 리스트에서 같은 인덱스를 가진
   항목에 해당합니다. 각 문자열은 줄 바꿈으로 끝납니다; 소스 텍스트 줄
   이 "None"이 아닌 항목의 경우, 문자열에 내부 줄 바꿈도 포함될 수 있
   습니다.

traceback.format_exception_only(etype, value)

   트레이스백의 예외 부분을 포맷합니다. 인자는 "sys.last_type"과
   "sys.last_value"에서 제공하는 것과 같은 예외 형과 값입니다. 반환 값
   은 각각 줄 바꿈으로 끝나는 문자열의 리스트입니다. 일반적으로, 리스
   트는 단일 문자열을 포함합니다; 그러나, "SyntaxError" 예외의 경우,
   문법 에러가 발생한 위치에 대한 자세한 정보를 (인쇄될 때) 표시하는
   여러 줄을 포함합니다. 어떤 예외가 발생했는지를 나타내는 메시지는 리
   스트에서 항상 마지막 문자열입니다.

traceback.format_exception(etype, value, tb, limit=None, chain=True)

   스택 트레이스와 예외 정보를 포맷합니다. 인자는 "print_exception()"
   의 해당하는 인자와 같은 의미입니다. 반환 값은 각각 줄 바꿈으로 끝나
   고 일부는 내부 줄 바꿈을 포함하는 문자열의 리스트입니다. 이 줄들을
   이어붙여서 인쇄하면, "print_exception()"과 정확히 같은 텍스트가 인
   쇄됩니다.

   버전 3.5에서 변경: *etype* 인자는 무시되고 *value* 형에서 유추됩니
   다.

traceback.format_exc(limit=None, chain=True)

   이것은 "print_exc(limit)"와 비슷하지만, 파일로 인쇄하는 대신 문자열
   을 반환합니다.

traceback.format_tb(tb, limit=None)

   "format_list(extract_tb(tb, limit))"의 줄임 표현입니다.

traceback.format_stack(f=None, limit=None)

   "format_list(extract_stack(f, limit))"의 줄임 표현입니다.

traceback.clear_frames(tb)

   각 프레임 객체의 "clear()" 메서드를 호출하여 트레이스백 *tb*에 있는
   모든 스택 프레임의 지역 변수를 지웁니다.

   버전 3.4에 추가.

traceback.walk_stack(f)

   주어진 프레임에서 "f.f_back"을 따라 스택을 걸어가며 각 프레임의 프
   레임과 줄 번호를 산출(yield)합니다. *f*가 "None"이면, 현재 스택이
   사용됩니다. 이 도우미는 "StackSummary.extract()"와 함께 사용됩니다.

   버전 3.5에 추가.

traceback.walk_tb(tb)

   "tb_next"를 따라 트레이스백을 걸으면서 각 프레임의 프레임과 줄 번호
   를 산출(yield)합니다. 이 도우미는 "StackSummary.extract()"와 함께
   사용됩니다.

   버전 3.5에 추가.

이 모듈은 또한 다음과 같은 클래스를 정의합니다:


"TracebackException" 객체
=========================

버전 3.5에 추가.

"TracebackException" 객체는 실제 예외에서 만들어져 나중에 인쇄하기 위
한 데이터를 경량 방식으로 포착합니다.

class traceback.TracebackException(exc_type, exc_value, exc_traceback, *, limit=None, lookup_lines=True, capture_locals=False)

   나중에 렌더링하기 위해 예외를 포착합니다. *limit*, *lookup_lines*
   및 *capture_locals*는 "StackSummary" 클래스와 같습니다.

   locals가 포착되면, 트레이스백에도 표시됨에 유의하십시오.

   __cause__

      원래 "__cause__"의 "TracebackException".

   __context__

      원래 "__context__"의 "TracebackException".

   __suppress_context__

      원래 예외의 "__suppress_context__" 값.

   stack

      트레이스백을 나타내는 "StackSummary".

   exc_type

      원래 트레이스백의 클래스.

   filename

      문법 에러일 때 - 에러가 발생한 파일 이름.

   lineno

      문법 에러일 때 - 에러가 발생한 줄 번호.

   text

      문법 에러일 때 - 에러가 발생한 텍스트.

   offset

      문법 에러일 때 - 에러가 발생한 텍스트에서의 오프셋.

   msg

      문법 에러일 때 - 컴파일러 에러 메시지.

   classmethod from_exception(exc, *, limit=None, lookup_lines=True, capture_locals=False)

      나중에 렌더링하기 위해 예외를 포착합니다. *limit*,
      *lookup_lines* 및 *capture_locals*는 "StackSummary" 클래스와 같
      습니다.

      locals가 포착되면, 트레이스백에도 표시됨에 유의하십시오.

   format(*, chain=True)

      예외를 포맷합니다.

      *chain*이 "True"가 아니면, "__cause__"와 "__context__"는 포맷되
      지 않습니다.

      반환 값은 각각 줄 바꿈으로 끝나고 일부는 내부 줄 바꿈을 포함하는
      문자열의 제너레이터입니다. "print_exception()"은 단지 파일에 줄
      을 인쇄하는 이 메서드를 둘러싸는 래퍼입니다.

      어떤 예외가 발생했는지를 나타내는 메시지는 항상 출력의 마지막 문
      자열입니다.

   format_exception_only()

      트레이스백의 예외 부분을 포맷합니다.

      반환 값은 각각 줄 바꿈으로 끝나는 문자열의 제너레이터입니다.

      일반적으로, 제너레이터는 단일 문자열을 방출합니다; 그러나
      "SyntaxError" 예외의 경우, 문법 에러가 발생한 위치에 대한 자세한
      정보를 (인쇄할 때) 표시하는 여러 줄을 방출합니다.

      어떤 예외가 발생했는지를 나타내는 메시지는 항상 출력의 마지막 문
      자열입니다.


"StackSummary" 객체
===================

버전 3.5에 추가.

"StackSummary" 객체는 포맷 준비가 된 호출 스택을 나타냅니다.

class traceback.StackSummary

   classmethod extract(frame_gen, *, limit=None, lookup_lines=True, capture_locals=False)

      ("walk_stack()"이나 "walk_tb()"에서 반환된 것과 같은) 프레임 제
      너레이터로 "StackSummary" 객체를 생성합니다.

      *limit*가 제공되면, *frame_gen*에서 이 수 만큼의 프레임만 취합니
      다. *lookup_lines*가 "False"이면, 반환된 "FrameSummary" 객체는
      아직 해당 줄을 읽지 않아서 "StackSummary"를 만드는 비용을 줄입니
      다 (실제로 포맷되지 않을 수 있다면 유용 할 수 있습니다).
      *capture_locals*가 "True"이면, 각 "FrameSummary"의 지역 변수는
      객체 표현(representation)으로 포착됩니다.

   classmethod from_list(a_list)

      제공된 "FrameSummary" 객체의 리스트나 이전 스타일의 튜플 리스트
      로 "StackSummary" 객체를 생성합니다. 각 튜플은 파일명(filename),
      줄 번호(lineno), 이름(name), 줄(line)을 요소로 하는 4-튜플이어야
      합니다.

   format()

      인쇄 준비가 된 문자열의 리스트를 반환합니다. 결과 리스트의 각 문
      자열은 스택의 단일 프레임에 해당합니다. 각 문자열은 줄 바꿈으로
      끝납니다; 소스 텍스트 줄이 있는 항목의 경우, 문자열에 내부 줄 바
      꿈도 포함될 수 있습니다.

      같은 프레임과 줄의 긴 시퀀스의 경우, 처음 몇 번의 반복이 표시된
      다음, 정확한 추가의 반복 횟수를 나타내는 요약 줄이 표시됩니다.

      버전 3.6에서 변경: 반복되는 프레임의 긴 시퀀스가 이제 축약됩니다
      .


"FrameSummary" 객체
===================

버전 3.5에 추가.

"FrameSummary" 객체는 트레이스백에서 단일 프레임을 나타냅니다.

class traceback.FrameSummary(filename, lineno, name, lookup_line=True, locals=None, line=None)

   포맷되거나 인쇄 중인 트레이스백이나 스택의 단일 프레임을 나타냅니다
   . 선택적으로 문자열로 변환된 버전의 프레임 지역 변수를 포함할 수 있
   습니다. *lookup_line*이 "False"이면, "FrameSummary"의 "line" 어트리
   뷰트에 액세스할 때까지 (튜플로 캐스트 할 때도 발생합니다) 소스 코드
   를 찾지 않습니다. "line"은 직접 제공될 수 있으며, 줄 조회가 전혀 발
   생하지 않도록 합니다. *locals*는 선택적 지역 변수 딕셔너리이며, 제
   공되면 변수 표현(representation)은 나중에 표시할 수 있도록 요약에
   저장됩니다.


트레이스백 예제
===============

이 간단한 예제는 표준 파이썬 대화식 인터프리터 루프와 비슷하지만 (하지
만 덜 유용한) 기본적인 읽기-평가-인쇄 루프를 구현합니다. 인터프리터 루
프의 더욱 완전한 구현은 "code" 모듈을 참조하십시오.

   import sys, traceback

   def run_user_code(envdir):
       source = input(">>> ")
       try:
           exec(source, envdir)
       except Exception:
           print("Exception in user code:")
           print("-"*60)
           traceback.print_exc(file=sys.stdout)
           print("-"*60)

   envdir = {}
   while True:
       run_user_code(envdir)

다음 예제는 예외와 추적을 인쇄하고 포맷하는 다양한 방법을 보여줍니다:

   import sys, traceback

   def lumberjack():
       bright_side_of_death()

   def bright_side_of_death():
       return tuple()[0]

   try:
       lumberjack()
   except IndexError:
       exc_type, exc_value, exc_traceback = sys.exc_info()
       print("*** print_tb:")
       traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
       print("*** print_exception:")
       # exc_type below is ignored on 3.5 and later
       traceback.print_exception(exc_type, exc_value, exc_traceback,
                                 limit=2, file=sys.stdout)
       print("*** print_exc:")
       traceback.print_exc(limit=2, file=sys.stdout)
       print("*** format_exc, first and last line:")
       formatted_lines = traceback.format_exc().splitlines()
       print(formatted_lines[0])
       print(formatted_lines[-1])
       print("*** format_exception:")
       # exc_type below is ignored on 3.5 and later
       print(repr(traceback.format_exception(exc_type, exc_value,
                                             exc_traceback)))
       print("*** extract_tb:")
       print(repr(traceback.extract_tb(exc_traceback)))
       print("*** format_tb:")
       print(repr(traceback.format_tb(exc_traceback)))
       print("*** tb_lineno:", exc_traceback.tb_lineno)

예제의 출력은 다음과 유사합니다:

   *** print_tb:
     File "<doctest...>", line 10, in <module>
       lumberjack()
   *** print_exception:
   Traceback (most recent call last):
     File "<doctest...>", line 10, in <module>
       lumberjack()
     File "<doctest...>", line 4, in lumberjack
       bright_side_of_death()
   IndexError: tuple index out of range
   *** print_exc:
   Traceback (most recent call last):
     File "<doctest...>", line 10, in <module>
       lumberjack()
     File "<doctest...>", line 4, in lumberjack
       bright_side_of_death()
   IndexError: tuple index out of range
   *** format_exc, first and last line:
   Traceback (most recent call last):
   IndexError: tuple index out of range
   *** format_exception:
   ['Traceback (most recent call last):\n',
    '  File "<doctest...>", line 10, in <module>\n    lumberjack()\n',
    '  File "<doctest...>", line 4, in lumberjack\n    bright_side_of_death()\n',
    '  File "<doctest...>", line 7, in bright_side_of_death\n    return tuple()[0]\n',
    'IndexError: tuple index out of range\n']
   *** extract_tb:
   [<FrameSummary file <doctest...>, line 10 in <module>>,
    <FrameSummary file <doctest...>, line 4 in lumberjack>,
    <FrameSummary file <doctest...>, line 7 in bright_side_of_death>]
   *** format_tb:
   ['  File "<doctest...>", line 10, in <module>\n    lumberjack()\n',
    '  File "<doctest...>", line 4, in lumberjack\n    bright_side_of_death()\n',
    '  File "<doctest...>", line 7, in bright_side_of_death\n    return tuple()[0]\n']
   *** tb_lineno: 10

다음 예제는 스택을 인쇄하고 포맷하는 다양한 방법을 보여줍니다:

   >>> import traceback
   >>> def another_function():
   ...     lumberstack()
   ...
   >>> def lumberstack():
   ...     traceback.print_stack()
   ...     print(repr(traceback.extract_stack()))
   ...     print(repr(traceback.format_stack()))
   ...
   >>> another_function()
     File "<doctest>", line 10, in <module>
       another_function()
     File "<doctest>", line 3, in another_function
       lumberstack()
     File "<doctest>", line 6, in lumberstack
       traceback.print_stack()
   [('<doctest>', 10, '<module>', 'another_function()'),
    ('<doctest>', 3, 'another_function', 'lumberstack()'),
    ('<doctest>', 7, 'lumberstack', 'print(repr(traceback.extract_stack()))')]
   ['  File "<doctest>", line 10, in <module>\n    another_function()\n',
    '  File "<doctest>", line 3, in another_function\n    lumberstack()\n',
    '  File "<doctest>", line 8, in lumberstack\n    print(repr(traceback.format_stack()))\n']

이 마지막 예제는 마지막 몇 가지 포매팅 함수를 예시합니다:

   >>> import traceback
   >>> traceback.format_list([('spam.py', 3, '<module>', 'spam.eggs()'),
   ...                        ('eggs.py', 42, 'eggs', 'return "bacon"')])
   ['  File "spam.py", line 3, in <module>\n    spam.eggs()\n',
    '  File "eggs.py", line 42, in eggs\n    return "bacon"\n']
   >>> an_error = IndexError('tuple index out of range')
   >>> traceback.format_exception_only(type(an_error), an_error)
   ['IndexError: tuple index out of range\n']
