Python 코드를 분석하거나 변환할 때 추상 구문 트리(AST)는 핵심적인 중간 표현입니다. 표준 라이브러리 ast는 소스코드를 트리 구조로 변환해주지만, 수정된 AST를 다시 실행 가능한 Python 코드로 되돌리려면 외부 패키지가 필요합니다. 이번 글에서는 astor와 astunparse 두 도구의 특징과 적절한 사용 상황을 살펴봅니다.
AST 개념 정리
AST는 소스코드의 구문적 구조를 계층적으로 표현한 트리입니다. 예를 들어 다음 코드:
x = 10 * 5
는 다음과 같은 트리로 변환됩니다:
Module
└── Expr
└── Assign
├── Name(id='x')
└── BinOp
├── Constant(10)
├── Mult
└── Constant(5)
AST를 활용하면 문자열 조작 없이 코드의 논리적 구조를 안전하게 변경할 수 있습니다.
astor 라이브러리
astor는 AST를 Python 소스코드로 변환하는 기능에 초점을 맞춘 도구로, 생성되는 코드의 가독성과 형식을 세밀하게 제어할 수 있습니다.
설치 및 기본 사용
pip install astor
import ast
import astor
src = "result = base ** 2"
parsed = ast.parse(src)
print(astor.to_source(parsed))
복잡한 구조 처리
중첩된 제어 구조도 읽기 좋은 형태로 출력합니다:
snippet = """
def calculate(items):
total = 0
for val in items:
if val > 0:
total += val
return total
"""
tree = ast.parse(snippet)
print(astor.to_source(tree))
출력 결과는 들여쓰기와 공백이 적절히 배치되어 있습니다.
astunparse 라이브러리
astunparse는 단순히 AST를 문자열로 되돌리는 것에 중점을 둔 경량 도구입니다.
설치 및 사용법
pip install astunparse
import ast
import astunparse
src = "result = base ** 2"
parsed = ast.parse(src)
print(astunparse.unparse(parsed))
출력 특성
기능적으로는 충실하지만, 코드 스타일에 대한 제어는 제한적입니다:
compact = "def g(x,y):return x*y"
tree = ast.parse(compact)
print(astunparse.unparse(tree))
결과는 실행 가능한 코드이지만, astor만큼의 서식 최적화는 기대하기 어렵습니다.
두 도구의 비교
| 특성 | astor | astunparse |
|---|---|---|
| 주요 목적 | 고품질 코드 생성 | AST 역변환 |
| 형식 제어 | 상세한 옵션 제공 | 최소한의 제어 |
| 코드 가독성 | 높음 | 보통 |
| 의존성 | 중간 | 낮음 |
Python 3.9+ 내장 기능
Python 3.9부터는 표준 라이브러리에 ast.unparse()가 추가되어 astunparse와 유사한 기능을 별도 설치 없이 사용할 수 있습니다:
import ast
tree = ast.parse("value = arr[0] + 1")
print(ast.unparse(tree))
실전 예제: AST 변환 및 복원
변수명을 자동으로 변경하는 작업을 수행해봅니다.
AST 변환 로직
import ast
class RenameTransformer(ast.NodeTransformer):
def visit_Name(self, node):
if node.id == 'old_var':
renamed = ast.Name(id='new_var', ctx=node.ctx)
return ast.copy_location(renamed, node)
return node
source = "old_var = old_var * 2"
tree = ast.parse(source)
transformed = RenameTransformer().visit(tree)
ast.fix_missing_locations(transformed)
astor로 복원
import astor
print(astor.to_source(transformed))
astunparse로 원
import astunparse
print(astunparse.unparse(transformed))
두 경우 모두 new_var = new_var * 2를 출력합니다.
선택 가이드
astor를 선택할 때:
- 생성된 코드가 사람이 읽기 좋아야 할 때
- 들여쓰기, 공백 등 형식을 조정해야 할 때
- 코드 생성기나 리팩토링 도구를 개발할 때
astunparse를 선택할 때:
- 간단한 스크립트에서 빠르게 결과를 확인할 때
- 외부 의존성을 최소화하고 싶을 때
- Python 3.9 미만에서 표준 라이브러리만으로는 부족할 때
ast.unparse()를 선택할 때:
- Python 3.9 이상 환경에서 추가 패키지 설치를 피하고 싶을 때
- 기본적인 역파싱 기능으로 충분할 때