symtable — 컴파일러 심볼 테이블 접근
symtable — 컴파일러 심볼 테이블 접근
심볼 테이블(symbol table)은 컴파일러가 바이트코드를 만들기 직전에 AST에서 생성해요. 이 심볼 테이블이 코드에 있는 모든 식별자의 스코프(범위)를 계산하는 역할을 하죠. symtable 모듈은 바로 이 테이블들을 들여다볼 수 있는 인터페이스를 제공해요.
출처: Python 표준 라이브러리
본문
심볼 테이블 생성
symtable.symtable(code, filename, compile_type) — 파이썬 소스 코드에 대한 최상위 SymbolTable을 반환해요. filename은 코드를 담고 있는 파일의 이름이고, compile_type은 compile()의 mode 인자와 비슷한 역할을 해요.
심볼 테이블 살펴보기
class symtable.SymbolTableType — SymbolTable 객체의 종류를 나타내는 열거형이에요.
MODULE = "module"— 모듈의 심볼 테이블에 쓰여요.FUNCTION = "function"— 함수의 심볼 테이블에 쓰여요.CLASS = "class"— 클래스의 심볼 테이블에 쓰여요.
다음 멤버들은 서로 다른 종류의 어노테이션 스코프를 가리켜요.
ANNOTATION = "annotation"—from __future__ import annotations가 활성화되어 있을 때 어노테이션에 쓰여요.TYPE_ALIAS = "type alias"—type구문의 심볼 테이블에 쓰여요.TYPE_PARAMETERS = "type parameters"— 제네릭 함수나 제네릭 클래스의 심볼 테이블에 쓰여요.TYPE_VARIABLE = "type variable"— 형식적인 의미에서 단일 타입 변수의 bound, constraint 튜플, 또는 기본값에 대한 심볼 테이블에 쓰여요. 즉TypeVar,TypeVarTuple,ParamSpec객체를 말해요(뒤의 둘은 bound나 constraint 튜플을 지원하지 않아요).
버전 3.13에 추가됨.
class symtable.SymbolTable — 하나의 블록에 대한 네임스페이스 테이블이에요. 생성자는 공개되어 있지 않아요.
get_type()— 심볼 테이블의 종류를 반환해요. 가능한 값은SymbolTableType열거형의 멤버들이에요. 버전 3.12에서 변경: 반환 값으로'annotation','TypeVar bound','type alias','type parameter'가 추가됨. 버전 3.13에서 변경: 반환 값이SymbolTableType열거형의 멤버가 됨. 반환되는 문자열의 정확한 값은 나중에 바뀔 수 있으니, 하드코딩된 문자열 대신SymbolTableType멤버를 쓰는 것을 권장해요.get_id()— 테이블의 식별자를 반환해요.get_name()— 테이블의 이름을 반환해요. 클래스에 대한 테이블이면 클래스의 이름, 함수에 대한 테이블이면 함수의 이름, 전역 테이블이면'top'(get_type()이'module'을 반환해요)이에요. 제네릭 클래스·함수·타입 별칭에 쓰이는 타입 파라미터 스코프에서는 그 바탕이 되는 클래스·함수·타입 별칭의 이름이고, 타입 별칭 스코프에서는 타입 별칭의 이름,TypeVarbound 스코프에서는 그TypeVar의 이름이에요.get_lineno()— 이 테이블이 나타내는 블록의 첫 줄 번호를 반환해요.is_optimized()— 이 테이블의 지역 변수들을 최적화할 수 있으면True를 반환해요.is_nested()— 블록이 중첩된 클래스 또는 함수면True를 반환해요.has_children()— 블록 안에 중첩된 네임스페이스가 있으면True를 반환해요. 이것들은get_children()으로 얻을 수 있어요.get_identifiers()— 테이블 안에 있는 심볼 이름들을 담은 뷰 객체를 반환해요 (뷰 객체 문서 참고).lookup(name)— 테이블에서name을 찾아Symbol인스턴스를 반환해요.get_symbols()— 테이블 안에 있는 이름들에 대한Symbol인스턴스 목록을 반환해요.get_children()— 중첩된 심볼 테이블들의 목록을 반환해요.
class symtable.Function — 함수 또는 메서드의 네임스페이스예요. SymbolTable에서 상속받아요.
get_parameters()— 이 함수의 파라미터 이름들을 담은 튜플을 반환해요.get_locals()— 이 함수의 지역 변수 이름들을 담은 튜플을 반환해요.get_globals()— 이 함수의 전역 변수 이름들을 담은 튜플을 반환해요.get_nonlocals()— 이 함수에서 명시적으로 선언된 nonlocal 이름들을 담은 튜플을 반환해요.get_frees()— 이 함수의 자유(클로저) 변수 이름들을 담은 튜플을 반환해요.
class symtable.Class — 클래스의 네임스페이스예요. SymbolTable에서 상속받아요.
get_methods()— 클래스에서 선언된 메서드류 함수의 이름들을 담은 튜플을 반환해요. 여기서 'method'라는 말은 클래스 본문 안에서def나async def로 정의된 함수를 가리켜요. 더 깊은 스코프(예: 내부 클래스)에서 정의된 함수는get_methods()가 잡아내지 못해요. 예를 들어 볼게요.
>>> import symtable
>>> st = symtable.symtable('''
... def outer(): pass
...
... class A:
... def f():
... def w(): pass
...
... def g(self): pass
...
... @classmethod
... async def h(cls): pass
...
... global outer
... def outer(self): pass
... ''', 'test', 'exec')
>>> class_A = st.get_children()[2]
>>> class_A.get_methods()
('f', 'g', 'h')
A().f()가 실행 시점에 TypeError를 발생시키긴 하지만, A.f는 여전히 메서드류 함수로 간주돼요.
버전 3.14부터 폐기(deprecated), 버전 3.16에서 제거될 예정.
class symtable.Symbol — 소스 안의 식별자에 대응하는 SymbolTable의 한 항목이에요. 생성자는 공개되어 있지 않아요.
get_name()— 심볼의 이름을 반환해요.is_referenced()— 심볼이 자기 블록 안에서 사용되면True를 반환해요.is_imported()— 심볼이 import 문으로 만들어졌으면True를 반환해요.is_parameter()— 심볼이 파라미터면True를 반환해요.is_type_parameter()— 심볼이 타입 파라미터면True를 반환해요. (버전 3.14에 추가됨.)is_global()— 심볼이 전역이면True를 반환해요.is_nonlocal()— 심볼이 nonlocal이면True를 반환해요.is_declared_global()— 심볼이global문으로 전역으로 선언되었으면True를 반환해요.is_local()— 심볼이 자기 블록에 지역이면True를 반환해요.is_annotated()— 심볼이 어노테이션되어 있으면True를 반환해요. (버전 3.6에 추가됨.)is_free()— 심볼이 자기 블록에서 참조만 되고 할당되지는 않으면True를 반환해요.is_free_class()— 클래스 스코프 심볼이 메서드의 관점에서 자유(free)면True를 반환해요. 다음 예를 볼게요.
def f():
x = 1 # function-scoped
class C:
x = 2 # class-scoped
def method(self):
return x
이 예에서 클래스 스코프의 x는 C.method의 관점에서 자유로 간주돼요. 그래서 실행 시점에 C.method가 반환하는 값은 2가 아니라 1이 되는 거예요. (버전 3.14에 추가됨.)
is_assigned()— 심볼이 자기 블록 안에서 할당되면True를 반환해요.is_comp_iter()— 심볼이 컴프리헨션 반복 변수면True를 반환해요. (버전 3.14에 추가됨.)is_comp_cell()— 심볼이 인라인된 컴프리헨션 안의 셀이면True를 반환해요. (버전 3.14에 추가됨.)is_namespace()— 이름 바인딩이 새 네임스페이스를 도입하면True를 반환해요. 이름이 함수나 클래스 문의 대상으로 쓰이면 참이 돼요. 예를 들어 볼게요.
>>> table = symtable.symtable("def some_func(): pass", "string", "exec")
>>> table.lookup("some_func").is_namespace()
True
한 이름이 여러 객체에 바인딩될 수도 있다는 점을 기억하세요. 결과가 True여도 그 이름이 int나 list 같은 다른 객체에도 바인딩되어 있을 수 있고, 그런 객체는 새 네임스페이스를 도입하지 않아요.
get_namespaces()— 이 이름에 바인딩된 네임스페이스들의 목록을 반환해요.get_namespace()— 이 이름에 바인딩된 네임스페이스를 반환해요. 둘 이상이거나 하나도 없으면ValueError를 발생시켜요.
명령줄 사용
버전 3.13에 추가됨.
symtable 모듈은 명령줄에서 스크립트로 실행할 수 있어요.
python -m symtable [infile...]
지정한 파이썬 소스 파일들에 대한 심볼 테이블을 생성해 stdout으로 덤프해요. 입력 파일을 지정하지 않으면 stdin에서 내용을 읽어요.