Python AST 역직렬화 도구 비교: astor와 astunparse 활용법

Python 코드를 분석하거나 변환할 때 추상 구문 트리(AST)는 핵심적인 중간 표현입니다. 표준 라이브러리 ast는 소스코드를 트리 구조로 변환해주지만, 수정된 AST를 다시 실행 가능한 Python 코드로 되돌리려면 외부 패키지가 필요합니다. 이번 글에서는 astorastunparse 두 도구의 특징과 적절한 사용 상황을 살펴봅니다.

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만큼의 서식 최적화는 기대하기 어렵습니다.

두 도구의 비교

특성astorastunparse
주요 목적고품질 코드 생성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 이상 환경에서 추가 패키지 설치를 피하고 싶을 때
  • 기본적인 역파싱 기능으로 충분할 때

태그: AST astor astunparse python-code-generation static-analysis

7월 2일 18:21에 게시됨