tokenize — Python 소스용 토크나이저
tokenize — Python 소스용 토크나이저
tokenize 모듈은 Python으로 구현된 Python 소스 코드용 어휘 스캐너(lexical scanner)를 제공해요. 이 모듈의 스캐너는 주석도 토큰으로 반환하므로, 화면 표시용 컬러라이저(colorizer)를 포함한 "pretty-printer"를 구현하는 데 유용해요.
토큰 스트림 처리를 단순화하기 위해 모든 연산자와 구분자 토큰, 그리고 Ellipsis는 일반 OP 토큰 타입으로 반환돼요. 정확한 타입은 tokenize.tokenize()에서 반환된 named tuple의 exact_type 속성을 확인해 결정할 수 있어요.
본문
경고: 이 모듈의 함수는 문법적으로 유효한 Python 코드(즉
ast.parse()로 파싱할 때 예외를 일으키지 않는 코드)만 파싱하도록 설계되었어요. 유효하지 않은 Python 코드를 제공할 때 이 모듈 함수의 동작은 정의되지 않으며 언제든 바뀔 수 있어요.
입력 토큰화 (Tokenizing Input)
주요 진입점은 제너레이터예요:
tokenize.tokenize(readline)
tokenize() 제너레이터는 readline 인자 하나를 요구하며, 이는 파일 객체의 io.IOBase.readline() 메서드와 같은 인터페이스를 제공하는 호출 가능 객체여야 해요. 함수를 호출할 때마다 입력 한 줄을 bytes로 반환해야 해요.
제너레이터는 다음 구성원을 가진 5-tuple을 생성해요: 토큰 타입; 토큰 문자열; 소스에서 토큰이 시작되는 행과 열을 지정하는 int 2-tuple (srow, scol); 토큰이 끝나는 행과 열을 지정하는 int 2-tuple (erow, ecol); 그리고 토큰이 발견된 줄. 전달되는 줄(마지막 튜플 항목)은 물리적 줄이에요. 5-tuple은 type, string, start, end, line 필드 이름을 가진 named tuple로 반환돼요.
반환된 named tuple에는 OP 토큰의 정확한 연산자 타입을 담는 exact_type이라는 추가 속성이 있어요. 다른 모든 토큰 타입에서 exact_type은 named tuple의 type 필드와 같아요.
tokenize()는 PEP 263에 따라 UTF-8 BOM이나 인코딩 쿠키를 찾아 파일의 소스 인코딩을 결정해요.
tokenize.generate_tokens(readline)
bytes 대신 unicode 문자열을 읽어 소스를 토큰화해요. tokenize()와 마찬가지로 readline 인자는 단일 입력 줄을 반환하는 호출 가능 객체예요. 다만 generate_tokens()는 readline이 bytes가 아니라 str 객체를 반환할 것을 기대해요. 결과는 tokenize()와 똑같이 named tuple을 생성하는 iterator이며, ENCODING 토큰은 만들지 않아요.
token 모듈의 모든 상수도 tokenize에서 내보내집니다.
tokenize.untokenize(iterable)
토큰을 다시 Python 소스 코드로 변환해요. iterable은 최소 두 요소(토큰 타입과 토큰 문자열)를 가진 시퀀스를 반환해야 해요. 추가 시퀀스 요소는 무시돼요.
결과는 입력과 다시 일치하도록 토큰화된다는 것이 보장되어 변환이 무손실이고 왕복(round-trip)이 보장돼요. 이 보장은 토큰 타입과 토큰 문자열에만 적용되며, 토큰 사이의 간격(열 위치)은 바뀔 수 있어요.
ENCODING 토큰(즉 tokenize()가 출력하는 첫 번째 토큰 시퀀스)으로 인코딩된 bytes를 반환해요. 입력에 인코딩 토큰이 없으면 대신 str을 반환해요.
tokenize.detect_encoding(readline)
Python 소스 파일을 디코딩하는 데 사용해야 하는 인코딩을 감지하는 데 사용돼요. tokenize() 제너레이터와 같은 방식으로 readline 인자 하나를 요구해요.
readline을 최대 두 번 호출하고, 사용된 인코딩(문자열)과 읽은 줄(디코딩되지 않은 bytes) 목록을 반환해요. PEP 263에 지정된 UTF-8 BOM 또는 인코딩 쿠키의 존재에서 인코딩을 감지해요. BOM과 쿠키가 모두 있지만 일치하지 않으면 SyntaxError가 발생해요. BOM이 발견되면 'utf-8-sig'가 인코딩으로 반환된다는 점에 주의하세요. 인코딩이 지정되지 않으면 기본 'utf-8'을 반환해요.
open()은 detect_encoding()을 사용해 파일 인코딩을 감지하므로, Python 소스 파일을 열 때는 open()을 사용하세요.
tokenize.open(filename)
detect_encoding()이 감지한 인코딩을 사용해 파일을 읽기 전용 모드로 열어요. (버전 3.2에서 추가)
exceptiontokenize.TokenError
여러 줄에 걸쳐 나눠질 수 있는 docstring이나 표현식이 파일 어디에서도 완성되지 않을 때 발생해요. 예:
"""Beginning of docstring
또는:
[1, 2, 3
명령줄 사용법 (Command-Line Usage)
tokenize 모듈은 명령줄에서 스크립트로 실행할 수 있어요:
python -m tokenize [-e] [filename.py]
옵션:
-h,--help— 도움말 메시지 출력 후 종료-e,--exact— 정확한 타입을 사용해 토큰 이름 표시
filename.py가 지정되면 그 내용이 stdout으로 토큰화돼요. 그렇지 않으면 stdin에서 토큰화를 수행해요.
예제 (Examples)
float 리터럴을 Decimal 객체로 변환하는 스크립트 재작성기 예제:
from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP
from io import BytesIO
def decistmt(s):
"""문장 문자열에서 float를 Decimal로 대체"""
result = []
g = tokenize(BytesIO(s.encode('utf-8')).readline) # 문자열 토큰화
for toknum, tokval, _, _, _ in g:
if toknum == NUMBER and '.' in tokval: # NUMBER 토큰 대체
result.extend([
(NAME, 'Decimal'), (OP, '('),
(STRING, repr(tokval)), (OP, ')')
])
else:
result.append((toknum, tokval))
return untokenize(result).decode('utf-8')
명령줄에서 토큰화하는 예제. say_hello() 함수를 가진 스크립트는 각 토큰의 좌표 범위, 토큰 이름, 토큰 값을 포함한 출력으로 토큰화돼요.
-e 옵션을 사용하면 정확한 토큰 타입 이름을 표시할 수 있어요(예: OP 대신 LPAR, RPAR, COLON 등).
프로그래밍 방식으로 파일을 토큰화하는 예:
import tokenize
with tokenize.open('hello.py') as f:
tokens = tokenize.generate_tokens(f.readline)
for token in tokens:
print(token)
또는 bytes를 직접 읽어 tokenize()로:
import tokenize
with open('hello.py', 'rb') as f:
tokens = tokenize.tokenize(f.readline)
for token in tokens:
print(token)