symtable — 컴파일러 심볼 테이블 접근

symtable — 컴파일러 심볼 테이블 접근

심볼 테이블(symbol table)은 컴파일러가 바이트코드를 만들기 직전에 AST에서 생성해요. 이 심볼 테이블이 코드에 있는 모든 식별자의 스코프(범위)를 계산하는 역할을 하죠. symtable 모듈은 바로 이 테이블들을 들여다볼 수 있는 인터페이스를 제공해요.

출처: Python 표준 라이브러리

본문

심볼 테이블 생성

symtable.symtable(code, filename, compile_type) — 파이썬 소스 코드에 대한 최상위 SymbolTable을 반환해요. filename은 코드를 담고 있는 파일의 이름이고, compile_typecompile()mode 인자와 비슷한 역할을 해요.

심볼 테이블 살펴보기

class symtable.SymbolTableTypeSymbolTable 객체의 종류를 나타내는 열거형이에요.

  • 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'을 반환해요)이에요. 제네릭 클래스·함수·타입 별칭에 쓰이는 타입 파라미터 스코프에서는 그 바탕이 되는 클래스·함수·타입 별칭의 이름이고, 타입 별칭 스코프에서는 타입 별칭의 이름, TypeVar bound 스코프에서는 그 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'라는 말은 클래스 본문 안에서 defasync 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

이 예에서 클래스 스코프의 xC.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에서 내용을 읽어요.