Python에서의 다양한 파일 확장자와 역할
Python 개발 과정에서는 여러 종류의 파일 형식이 사용되며, 각각은 고유한 목적과 처리 방식을 가집니다.
.py – 소스 코드 파일
일반적인 Python 스크립트 파일로, 텍스트 에디터로 편집 가능하며 인터프리터에 의해 직접 실행됩니다. 이 파일은 런타임 시점에 파싱되고 바이트코드로 변환되어 실행됩니다.
.pyc – 컴파일된 바이트코드 파일
- Python 인터프리터가 .py 파일을 컴파일하여 생성하는 바이너리 형식의 출력물입니다.
- 실행 속도 향상을 위해 사용되며, 동일한 소스가 반복 실행될 때 재컴파일을 방지합니다.
- 파이썬 버전마다 호환성이 달라, 특정 버전에서 생성된 .pyc는 다른 버전에서 로드되지 않을 수 있습니다.
- 기본적으로
__pycache__디렉터리 내부에module_name.cpython-XX.pyc형태로 저장됩니다.
.pyo – 최적화된 바이트코드 (Python 3.5 이전)
옵션 -O 또는 -OO를 사용해 실행 시 생성되는 최적화된 바이트코드입니다. Python 3.5 이후부터는 .pyo 확장자를 사용하지 않고, 대신 .opt-1.pyc 또는 .opt-2.pyc 형식으로 구분됩니다.
.pyd – 다이내믹 링크 라이브러리 모듈
윈도우 환경에서 C/C++ 등으로 작성된 외부 확장 모듈을 의미합니다. 실제로는 DLL이지만 Python에서 임포트 가능한 형식으로 제공되며, 주로 성능이 중요한 부분을 네이티브 코드로 구현할 때 사용됩니다.
.pyz – 압축된 실행 가능 파이썬 아카이브
Python 3.5부터 도입된 ZIP 기반 패키징 형식으로, 하나의 파일 안에 전체 애플리케이션과 의존성을 포함할 수 있습니다. 표준 라이브러리 zipapp 모듈을 통해 생성 및 관리할 수 있으며, 단일 배포 파일로서 유용합니다.
바이트코드 파일 생성 방법
.pyc 파일은 자동으로 생성되지 않으며, 명시적인 트리거가 필요합니다. 일반적으로 다음과 같은 두 가지 모듈을 활용합니다:
단일 파일 컴파일: py_compile
import py_compile
py_compile.compile('example.py')
이 코드는 현재 디렉터리에 __pycache__/example.cpython-39.pyc와 같은 이름의 파일을 생성합니다.
디렉터리 전체 컴파일: compileall
import compileall
compileall.compile_dir('src/')
또는 커맨드라인에서:
python -m compileall src/
모든 하위 디렉터리의 .py 파일들을 재귀적으로 찾아 바이트코드로 변환합니다.
최적화된 컴파일 수행
명령어에 -O 플래그를 추가하면 최적화된 바이트코드가 생성됩니다:
python -O -m compileall .
결과로 example.cpython-39.opt-1.pyc 파일이 생성되며, 이는 docstring 제거 및 일부 어설션 비활성화 등의 최적화를 포함합니다.
pyc 파일 직접 실행
생성된 .pyc 파일은 Python 인터프리터로 직접 실행 가능합니다:
python __pycache__/sample.cpython-39.pyc
출력 결과는 원본 .py 파일 실행 시와 동일하게 나타납니다. 이는 독립형 배포나 보안 감사 시 유용하게 활용될 수 있습니다.
바이트코드 역컴파일 도구: uncompyle6 활용법
uncompyle6는 다양한 파이썬 버전의 바이트코드를 원본 소스 코드로 복원할 수 있는 강력한 도구입니다.
설치 절차
pip install uncompyle6
설치 후 다음과 같이 기본 정보를 확인할 수 있습니다:
pip show uncompyle6
실제 디컴파일 예제
특정 .pyc 파일을 소스로 복원하는 명령:
uncompyle6 __pycache__/main.cpython-39.pyc > restored.py
결과 파일 restored.py에는 원본과 매우 유사한 코드가 포함됩니다:
# uncompyle6 version 3.8.0
# Python bytecode 3.9 (3425)
# Decompiled from: Python 3.9.1
# Embedded file name: main.py
print('Hello Python !')
# okay decompiling main.cpython-39.pyc
디렉터리 전체 재귀 디컴파일
다수의 파일을 한 번에 처리하기 위해 -r 옵션을 사용할 수 있습니다:
uncompyle6 -r -o ./output /path/to/pyc/files
이 경우 모든 .pyc/.pyo 파일이 탐색되어 지정된 출력 경로에 복원됩니다.
검증 기능 사용
--verify 플래그를 통해 복원된 코드가 원본 바이트코드와 일치하는지 검사할 수 있습니다:
uncompyle6 --verify sample.cpython-39.pyc
이 기능은 정확한 리버스 엔지니어링을 보장하는 데 중요합니다.
대체 디컴파일 도구 소개
Decompyle++
C++ 기반의 고성능 디컴파일러로, 일부 복잡한 바이트코드에 대해 더 나은 복원률을 제공합니다. GitHub 저장소에서 소스 코드를 제공하며, 컴파일 후 사용 가능합니다.
- 주요 장점: 빠른 처리 속도, 간결한 출력
- 단점: 최신 파이썬 문법 지원이 제한적일 수 있음
Easy Python Decompiler
GUI 기반 도구로, 기술적 배경이 부족한 사용자에게 적합합니다. SourceForge에서 배포되며, 드래그앤드롭 방식으로 .pyc 파일을 열 수 있습니다.
주의할 점은 오랜 시간 업데이트되지 않았을 가능성과, 최신 언어 기능에 대한 지원 부족입니다.
보안 및 법적 고려사항
디컴파일은 학습 및 정당한 유지보수 목적이 아닌 경우 저작권 침해로 간주될 수 있습니다. 항상 라이선스 조건을 확인하고, 허용 범위 내에서만 사용해야 합니다.