본문 바로가기
Python

[Py] dis 모듈 - Python

by ds31x 2025. 3. 11.

Python의 dis 모듈: 바이트코드 disassemble하기

Python은 인터프리터 언어지만, 실행 전에 source code (원시코드)를 bytecode (바이트코드) 라는 중간 형태로 컴파일하여 성능을 향상시킴.

  • 이 바이트코드는 Python의 가상 머신(보통 CPython VM)에서 실행됨.
  • 이를 disassemble(역어셈블)하여 분석할 수 있게 해주는 도구가 표준 라이브러리의 dis 모듈임.

2024.06.05 - [CE] - [CE] Bytecode (바이트코드)

 

[CE] Bytecode (바이트코드)

Bytecode (바이트코드)정의:Bytecode는 고수준 프로그래밍 언어로 작성된 source code를 중간 형태로 변환한 code 임.이는 특정 Virtual Machine (VM)에서 실행될 수 있도록 설계됨.가장 대표적인 예로 Java에서

ds31x.tistory.com

https://dsaint31.tistory.com/496

 

[Python] Interpreter and PVM (Python Virtual Machine)

Interpreter and PVM (Python Virtual Machine)더보기대학을 막 졸업해서 초보 프로그래머로 일을 할 때 개인적으로 가지고 있던 편견 중 하나가 script language를 매우 하찮게 생각하면서 오직 compiler language

dsaint31.tistory.com


dis 모듈 소개

  • dis 모듈은 Python 바이트코드를 '역어셈블(disassemble)'하여 인간이 읽을 수 있는 형태로 보여줌.
  • 일종의 Assembly Language 처럼 보이는 이 코드를 통해,
  • 실제 코드가 어떻게 실행되는지, 내부적으로 어떤 최적화가 이루어지는지 이해할 수 있음.

예제 코드:

import dis

def example():
    a = 3
    b = 7
    return a + b

dis.dis(example)

 

출력 결과:

  2           0 RESUME                   0
  3           2 LOAD_CONST               1 (3)
              4 STORE_FAST               0 (a)
  4           6 LOAD_CONST               2 (7)
              8 STORE_FAST               1 (b)
  5          10 LOAD_FAST                0 (a)
             12 LOAD_FAST                1 (b)
             14 BINARY_ADD
             16 RETURN_VALUE

Bytecode 이해하기

bytecode (바이트코드) 출력을 해석하는 방법은 다음과 같음:

  1. 첫 번째 열: 소스 코드의 줄 번호
  2. 두 번째 열: 바이트코드 내 명령어의 오프셋(위치)
  3. 세 번째 열: 명령어 이름(opcode)
  4. 네 번째 열: 명령어에 대한 인자(operand. 일부 문헌에선 argument라고도 함)
  5. 다섯 번째 열: 인자의 실제 값(괄호 안)

Python 가상 머신의 stack 기반 실행 모델

Python 가상 머신은 스택 기반으로 동작합니다. 대부분의 바이트코드 명령어는 이 스택을 조작하며 작업을 수행합니다:

  • LOAD 계열 명령어
    • LOAD_FAST, LOAD_CONST
    • 값을 스택에 푸시(push).
  • STORE 계열 명령어
    • 스택에서 값을 팝(pop)하여
    • 변수에 저장
  • 연산 명령어
    • BINARY_ADD
    • 스택에서 값들을 pop하여 연산 후 결과를 다시 스택에 push.

예를 들어, a + b 연산이 실행될 때 스택의 변화는 다음과 같음:

LOAD_FAST    0 (a)   # 스택: [a의 값]
LOAD_FAST    1 (b)   # 스택: [a의 값, b의 값]
BINARY_ADD           # 스택: [a+b의 결과]

스택 기반 모델은 JVM이나 .NET CLR과 같은 다른 가상 머신에서도 널리 사용되는 방식임.

주요 바이트코드 명령어

변수 관련 명령어

  • LOAD_CONST:
    • 상수 테이블에서 값을 가져와 스택에 Push.
    • 인자는 상수 테이블의 index.
  • STORE_FAST:
    • 스택 최상위 값을 지역 변수에 저장.
    • 인자는 지역 변수 테이블의 index.
  • LOAD_FAST:
    • 지역변수 배열에서 해당 index의 지역 변수의 값을 스택에 Push.
    • "FAST"는 가장 빠른 변수 접근 방식을 의미.
  • LOAD_GLOBAL:
    • 전역 변수나 내장 함수를 스택에 push.

연산 및 함수 호출

  • BINARY_ADD:
    • 스택의 상위 두 값을 pop하여
    • 더한 후 결과를 스택에 push.
  • CALL:
    • 함수를 호출.
    • 인자는 호출에 사용된 인자 개수.
  • RETURN_VALUE/RETURN_CONST:
    • 스택 최상위 값(또는 지정된 상수)을 함수의 반환 값으로 사용.

제어 흐름

  • RESUME: 함수 실행을 시작하거나 재개(Python 3.11+).
  • POP_TOP: 스택 최상위 값을 제거.

dis 모듈의 활용

dis 모듈은 다음과 같은 상황에서 유용함:

  1. 코드 최적화: 코드가 어떻게 컴파일되는지 확인하여 성능 병목을 식별할 수 있음.
  2. 디버깅: 복잡한 버그를 추적할 때 코드의 실제 실행 흐름을 이해하는 데 도움이 됨.
  3. 학습: Python의 내부 작동 방식을 더 깊이 이해할 수 있음.
  4. 메타프로그래밍: 코드 생성이나 조작을 위한 도구를 개발할 때 유용함.

사용관련 예제

2025.03.11 - [CE] - [Py] bytecode 분석 - dis 모듈

 

[Py] bytecode 분석 - dis 모듈

(main) script 부분Python에서 "main script"는 프로그램 실행을 시작하는 주 진입점이 되는 Python 파일 또는 source code를 의미함. 0 0 RESUME 0 1 2 LOAD_CONST 0 () 4 MAKE_FUNCTION 0 6 STORE_NAME 0 (func)RESUME 0: 코드 실행 시

ds31x.tistory.com