bdb — 디버거 프레임워크

bdb — 디버거 프레임워크 (Debugger framework)

브레이크포인트 설정이나 디버거를 통한 실행 관리 같은 기본 디버거 기능을 처리하는 모듈이에요.

출처: Python 표준 라이브러리

본문

bdb 모듈은 브레이크포인트 설정이나 디버거를 통한 실행 관리 같은 기본 디버거 기능을 처리해요.

다음 예외가 정의돼요:

exception bdb.BdbQuit

디버거를 종료하기 위해 Bdb 클래스가 발생시키는 예외예요.

bdb 모듈은 또한 두 클래스를 정의해요.

class bdb.Breakpoint(self, file, line, temporary=False, cond=None, funcname=None)

이 클래스는 임시 브레이크포인트, 무시 횟수(ignore count), 비활성화와 (재)활성화, 조건부를 구현해요.

브레이크포인트는 bpbynumber라는 리스트를 통해 번호로, bplist를 통해 (file, line) 쌍으로 인덱싱돼요. 전자는 Breakpoint 클래스의 단일 인스턴스를 가리키고, 후자는 한 줄에 브레이크포인트가 두 개 이상 있을 수 있으므로 해당 인스턴스들의 리스트를 가리켜요.

브레이크포인트를 만들 때 연결된 파일 이름은 표준(canonical) 형태여야 해요. funcname이 정의되면 함수의 첫 줄이 실행될 때 브레이크포인트 히트가 카운트돼요. 조건부 브레이크포인트는 항상 히트를 카운트해요.

Breakpoint 인스턴스 메서드:

  • deleteMe() — 파일/줄에 연결된 리스트에서 브레이크포인트를 삭제해요. 그 위치의 마지막 브레이크포인트라면 파일/줄 항목도 삭제해요.
  • enable() — 브레이크포인트를 활성화된 것으로 표시해요.
  • disable() — 브레이크포인트를 비활성화된 것으로 표시해요.
  • bpformat() — 브레이크포인트에 대한 모든 정보를 깔끔하게 포맷한 문자열을 반환해요: 브레이크포인트 번호, 임시 상태(del 또는 keep), 파일/줄 위치, 중단 조건, 무시할 횟수, 히트된 횟수. 3.2 버전에서 추가.
  • bpprint(out=None)bpformat()의 출력을 파일 out에, 또는 None이면 표준 출력에 인쇄해요.

Breakpoint 인스턴스 속성:

  • file — 브레이크포인트의 파일 이름.
  • linefile 안에서 브레이크포인트의 줄 번호.
  • temporary(file, line)의 브레이크포인트가 임시면 True.
  • cond(file, line)의 브레이크포인트를 평가하기 위한 조건.
  • funcname — 함수에 진입할 때 브레이크포인트가 히트되는지 여부를 정의하는 함수 이름.
  • enabled — 브레이크포인트가 활성화면 True.
  • bpbynumberBreakpoint 단일 인스턴스의 숫자 인덱스.
  • bplist(file, line) 튜플로 인덱싱된 Breakpoint 인스턴스의 사전.
  • ignore — 브레이크포인트를 무시할 횟수.
  • hits — 브레이크포인트가 히트된 횟수 카운트.

class bdb.Bdb(skip=None, backend='settrace')

Bdb 클래스는 일반적인 Python 디버거 베이스 클래스로 동작해요. 이 클래스는 trace 기능의 세부사항을 처리하고, 파생 클래스는 사용자 상호작용을 구현해야 해요. 표준 디버거 클래스(pdb.Pdb)가 그 예시예요.

skip 인자는 주어지면 glob 스타일 모듈 이름 패턴의 iterable이어야 해요. 디버거는 이 패턴 중 하나와 일치하는 모듈에서 시작된 프레임으로는 들어가지 않아요. 프레임이 특정 모듈에서 시작된 것으로 간주되는지는 프레임 globals의 __name__으로 결정돼요.

backend 인자는 Bdb에 사용할 백엔드를 지정해요. 'settrace' 또는 'monitoring'이 될 수 있어요. 'settrace'는 최고의 하위 호환성을 가진 sys.settrace()를 사용해요. 'monitoring' 백엔드는 Python 3.12에서 도입된 새 sys.monitoring을 사용하는데, 사용하지 않는 이벤트를 비활성화할 수 있으므로 훨씬 효율적일 수 있어요. 두 백엔드에 대해 정확한 인터페이스를 유지하려고 노력하고 있지만 몇 가지 차이가 있어요. 디버거 개발자는 더 나은 성능을 위해 'monitoring' 백엔드를 사용하는 것이 권장돼요.

3.1 버전 변경: skip 매개변수 추가.

3.14 버전 변경: backend 매개변수 추가.

보통 오버라이드할 필요가 없는 Bdb 메서드:

  • canonic(filename)filename의 표준 형태를 반환해요. 실제 파일 이름의 표준 형태는 운영체제에 의존적이고 대소문자가 정규화된 절대 경로예요. 인터랙티브 모드에서 생성된 stdin 같은 꺾쇠괄호가 있는 파일 이름은 변경 없이 반환돼요.

  • start_trace(self) — 추적을 시작해요. 'settrace' 백엔드의 경우 이 메서드는 sys.settrace(self.trace_dispatch)와 동일해요. 3.14 버전에서 추가.

  • stop_trace(self) — 추적을 중지해요. 'settrace' 백엔드의 경우 sys.settrace(None)과 동일해요. 3.14 버전에서 추가.

  • reset()botframe, stopframe, returnframe, quitting 속성을 디버깅을 시작할 준비가 된 값으로 설정해요.

  • trace_dispatch(frame, event, arg) — 디버깅되는 프레임의 trace 함수로 설치되는 함수예요. 반환값은 새 trace 함수예요(대부분의 경우 그 자체). 기본 구현은 실행될 이벤트의 유형(문자열로 전달)에 따라 프레임을 어떻게 디스패치할지 결정해요. event는 다음 중 하나일 수 있어요:

    • line — 새 코드 줄이 실행되려고 함.
    • call — 함수가 호출되거나 다른 코드 블록에 진입하려고 함.
    • return — 함수나 다른 코드 블록이 반환하려고 함.
    • exception — 예외가 발생함.
    • c_call — C 함수가 호출되려고 함.
    • c_return — C 함수가 반환함.
    • c_exception — C 함수가 예외를 발생시킴.

    Python 이벤트에 대해서는 전문화된 함수(아래 참고)가 호출돼요. C 이벤트에 대해서는 아무 조치가 취해지지 않아요. arg 매개변수는 이전 이벤트에 따라 달라져요. trace 함수에 대한 자세한 내용은 sys.settrace() 문서를, code와 frame 객체에 대한 자세한 내용은 표준 타입 계층(The standard type hierarchy)을 참고하세요.

  • dispatch_line(frame) — 디버거가 현재 줄에서 멈춰야 하면 user_line() 메서드(서브클래스에서 오버라이드해야 함)를 호출해요. quitting 플래그가 설정돼 있으면(user_line()에서 설정 가능) BdbQuit 예외를 발생시켜요. 그 범위에서 추가 추적을 위해 trace_dispatch() 메서드 참조를 반환해요.

  • dispatch_call(frame, arg) — 디버거가 이 함수 호출에서 멈춰야 하면 user_call() 메서드를 호출해요. quitting이 설정돼 있으면 BdbQuit을 발생시켜요. trace_dispatch() 참조를 반환해요.

  • dispatch_return(frame, arg) — 디버거가 이 함수 반환에서 멈춰야 하면 user_return() 메서드를 호출해요. quitting이 설정돼 있으면 BdbQuit을 발생시켜요. trace_dispatch() 참조를 반환해요.

  • dispatch_exception(frame, arg) — 디버거가 이 예외에서 멈춰야 하면 user_exception() 메서드를 호출해요. quitting이 설정돼 있으면 BdbQuit을 발생시켜요. trace_dispatch() 참조를 반환해요.

보통 파생 클래스가 오버라이드하지 않지만, 멈춤과 브레이크포인트의 정의를 재정의하려면 오버라이드할 수 있는 메서드:

  • is_skipped_module(module_name)module_name이 어떤 skip 패턴과도 일치하면 True를 반환해요.
  • stop_here(frame)frame이 스택에서 시작 프레임 아래에 있으면 True를 반환해요.
  • break_here(frame) — 이 줄에 유효한 브레이크포인트가 있으면 True를 반환해요. 줄 또는 함수 브레이크포인트가 존재하고 유효한지 확인해요. effective()의 정보에 기반해 임시 브레이크포인트를 삭제해요.
  • break_anywhere(frame)frame의 파일 이름에 어떤 브레이크포인트가 존재하면 True를 반환해요.

파생 클래스가 디버거 동작 제어를 위해 오버라이드해야 하는 메서드:

  • user_call(frame, argument_list) — 중단이 호출된 함수 안에서 멈출 수 있으면 dispatch_call()에서 호출돼요. argument_list는 더 이상 사용되지 않으며 항상 None이에요. 이 인자는 하위 호환성을 위해 유지돼요.
  • user_line(frame)stop_here() 또는 break_here()True를 반환할 때 dispatch_line()에서 호출돼요.
  • user_return(frame, return_value)stop_here()True를 반환할 때 dispatch_return()에서 호출돼요.
  • user_exception(frame, exc_info)stop_here()True를 반환할 때 dispatch_exception()에서 호출돼요.
  • do_clear(arg) — 브레이크포인트가 임시일 때 어떻게 제거해야 하는지 처리해요. 이 메서드는 파생 클래스가 구현해야 해요.

파생 클래스와 클라이언트가 스테핑 상태에 영향을 주기 위해 호출할 수 있는 메서드:

  • set_step() — 한 줄의 코드 후에 멈춰요.
  • set_next(frame) — 주어진 프레임 안이나 아래의 다음 줄에서 멈춰요.
  • set_return(frame) — 주어진 프레임에서 반환할 때 멈춰요.
  • set_until(frame, lineno=None) — 현재 것보다 큰 lineno를 가진 줄에 도달하거나 현재 프레임에서 반환할 때 멈춰요.
  • set_trace([frame])frame에서 디버깅을 시작해요. frame을 지정하지 않으면 호출자의 프레임에서 시작해요. 3.13 버전 변경: set_trace()는 실행될 다음 코드 줄이 아니라 즉시 디버거에 진입해요.
  • set_continue() — 브레이크포인트에서만 멈추거나 완료됐을 때 멈춰요. 브레이크포인트가 없으면 시스템 trace 함수를 None으로 설정해요.
  • set_quit()quitting 속성을 True로 설정해요. 이는 다음 dispatch_*() 메서드 호출에서 BdbQuit을 발생시켜요.

파생 클래스와 클라이언트가 브레이크포인트를 조작하기 위해 호출할 수 있는 메서드. 뭔가 잘못되면 오류 메시지 문자열을, 잘 되면 None을 반환해요:

  • set_break(filename, lineno, temporary=False, cond=None, funcname=None) — 새 브레이크포인트를 설정해요. 인자로 전달된 filename에 대해 lineno 줄이 존재하지 않으면 오류 메시지를 반환해요. filenamecanonic() 메서드에 설명된 대로 표준 형태여야 해요.
  • clear_break(filename, lineno)filenamelineno의 브레이크포인트를 삭제해요. 설정된 게 없으면 오류 메시지를 반환해요.
  • clear_bpbynumber(arg)Breakpoint.bpbynumber에서 인덱스 arg를 가진 브레이크포인트를 삭제해요. arg가 숫자가 아니거나 범위를 벗어나면 오류 메시지를 반환해요.
  • clear_all_file_breaks(filename)filename의 모든 브레이크포인트를 삭제해요. 설정된 게 없으면 오류 메시지를 반환해요.
  • clear_all_breaks() — 모든 기존 브레이크포인트를 삭제해요. 설정된 게 없으면 오류 메시지를 반환해요.
  • get_bpbynumber(arg) — 주어진 번호로 지정된 브레이크포인트를 반환해요. arg가 문자열이면 숫자로 변환돼요. arg가 숫자가 아닌 문자열이거나, 주어진 브레이크포인트가 존재한 적이 없거나 삭제됐으면 ValueError가 발생해요. 3.2 버전에서 추가.
  • get_break(filename, lineno)filenamelineno에 브레이크포인트가 있으면 True를 반환해요.
  • get_breaks(filename, lineno)filenamelineno에 대한 모든 브레이크포인트를 반환하거나, 설정된 게 없으면 빈 리스트를 반환해요.
  • get_file_breaks(filename)filename의 모든 브레이크포인트를 반환하거나, 설정된 게 없으면 빈 리스트를 반환해요.
  • get_all_breaks() — 설정된 모든 브레이크포인트를 반환해요.

파생 클래스와 클라이언트가 더 나은 성능을 위해 이벤트를 비활성화하고 재시작하는 데 호출할 수 있는 메서드. 'monitoring' 백엔드에서만 동작해요:

  • disable_current_event() — 다음에 restart_events()가 호출될 때까지 현재 이벤트를 비활성화해요. 디버거가 현재 줄에 관심이 없을 때 도움이 돼요. 3.14 버전에서 추가.
  • restart_events() — 비활성화된 모든 이벤트를 재시작해요. 이 함수는 user_* 메서드가 호출된 후 dispatch_* 메서드에서 자동으로 호출돼요. dispatch_* 메서드를 오버라이드하지 않으면 비활성화된 이벤트는 매 사용자 상호작용 후 재시작돼요. 3.14 버전에서 추가.

스택 트레이스를 나타내는 데이터 구조를 얻기 위해 호출할 수 있는 메서드:

  • get_stack(f, t) — 스택 트레이스의 (frame, lineno) 튜플 리스트와 크기를 반환해요. 가장 최근에 호출된 프레임이 리스트의 마지막이에요. size는 디버거가 호출된 프레임 아래에 있는 프레임의 수예요.
  • format_stack_entry(frame_lineno, lprefix=': ')(frame, lineno) 튜플인 스택 항목에 대한 정보가 담긴 문자열을 반환해요. 반환 문자열에는 표준(캐노니컬) 파일 이름, 함수 이름 또는 lambda, 입력 인자, 반환값, 코드 줄(존재한다면)이 포함돼요.

클라이언트가 문자열로 주어진 명령문을 디버깅하기 위해 호출할 수 있는 두 메서드:

  • run(cmd, globals=None, locals=None)exec() 함수를 통해 실행되는 명령문을 디버깅해요. globals는 기본적으로 __main__.__dict__이고, locals는 기본적으로 globals예요.
  • runeval(expr, globals=None, locals=None)eval() 함수를 통해 실행되는 표현식을 디버깅해요. globalslocalsrun()과 같은 의미예요.
  • runctx(cmd, globals, locals) — 하위 호환성을 위한 것. run() 메서드를 호출해요.
  • runcall(func, /, *args, **kwds) — 단일 함수 호출을 디버깅하고 그 결과를 반환해요.

마지막으로 모듈은 다음 함수를 정의해요:

bdb.checkfuncname(b, frame)

여기서 멈춰야 하는지 여부를 Breakpoint b가 설정된 방식에 따라 True를 반환해요. 줄 번호로 설정됐으면 b.lineframe의 것과 같은지 확인해요. 함수 이름으로 설정됐으면 올바른 프레임(올바른 함수)에 있고 첫 번째 실행 가능한 줄에 있는지 확인해야 해요.

bdb.effective(file, line, frame)

(active breakpoint, delete temporary flag) 또는 (None, None)을 작용할 브레이크포인트로 반환해요. 활성 브레이크포인트는 (file, line)(존재해야 함)에 대한 bplist의 첫 항목으로, 활성화되어 있고 checkfuncname()이 참이며 조건이 거짓이 아니고 무시 횟수가 양수가 아닌 것이에요. 임시 브레이크포인트가 삭제되어야 한다는 뜻의 플래그는 cond를 평가할 수 없을 때만 False예요(이 경우 무시 횟수는 무시돼요). 그런 항목이 없으면 (None, None)이 반환돼요.

bdb.set_trace()

호출자의 프레임에서 Bdb 인스턴스로 디버깅을 시작해요.