Python

tokenize — 파이썬 소스를 위한 토크나이저

소스 코드: Lib/tokenize.py


tokenize 모듈은 Python 소스 코드를 위한 어휘 스캐너를 제공하며, Python으로 구현되었습니다. 이 모듈의 스캐너는 주석도 토큰으로 반환하므로, 화면 디스플레이용 색상 표시기를 포함한 “pretty-printers”를 구현하는 데 유용합니다.

토큰 스트림 처리를 단순화하기 위해, 모든 연산자구분자 토큰과 Ellipsis는 범용 OP 토큰 유형을 사용하여 반환됩니다. 정확한 유형은 tokenize.tokenize()에서 반환된 네임드 튜플exact_type 프로퍼티를 확인하여 파악할 수 있습니다.

경고

이 모듈의 함수는 구문적으로 유효한 Python 코드(:func:`ast.parse`를 사용하여 파싱할 때 오류를 발생시키지 않는 코드)를 구문 분석하도록 설계되었음에 유의하십시오. 이 모듈의 동작은 유효하지 않은 Python 코드를 제공할 경우 정의되지 않으며, 언제든지 변경될 수 있습니다.

입력 토큰화하기

기본 진입점은 제너레이터입니다:

tokenize.tokenize(readline)

tokenize() 제너레이터는 하나의 인자 readline을 요구합니다. 이 인자는 파일 객체의 io.IOBase.readline() 메서드와 같은 인터페이스를 제공하는 콜러블 객체여야 합니다. 함수를 호출할 때마다 한 줄의 입력을 바이트열로 반환해야 합니다.

제너레이터는 다음 멤버를 갖는 5-튜플을 생성합니다: 토큰 유형; 토큰 문자열; 토큰이 소스에서 시작하는 줄과 열을 지정하는 정수의 2-튜플 (srow, scol); 토큰이 소스에서 끝나는 줄과 열을 지정하는 정수의 2-튜플 (erow, ecol)과 토큰이 발견된 줄. 전달된 줄(마지막 튜플 항목)은 물리적 줄입니다. 5-튜플은 필드 이름이 type string start end line네임드 튜플로 반환됩니다.

반환된 네임드 튜플에는 OP 토큰에 대한 정확한 연산자 유형이 포함된 exact_type이라는 추가 프로퍼티가 있습니다. 다른 모든 토큰 유형에서 exact_type은 네임드 튜플 type 필드와 같습니다.

버전 3.1에서 변경: 네임드 튜플에 대한 지원이 추가되었습니다.

버전 3.3에서 변경: exact_type에 대한 지원이 추가되었습니다.

tokenize()PEP 263에 따라 UTF-8 BOM이나 인코딩 쿠키를 찾아 파일의 소스 인코딩을 결정합니다.

tokenize.generate_tokens(readline)

바이트열 대신에 유니코드 문자열을 읽는 소스를 토큰화합니다.

tokenize()와 마찬가지로, readline 인자는 한 줄의 입력을 반환하는 콜러블입니다. 그러나, generate_tokens()readline이 바이트열이 아닌 문자열 객체를 반환할 것으로 기대합니다.

결과는 정확히 tokenize()처럼 네임드 튜플을 산출하는 이터레이터입니다. ENCODING 토큰을 산출하지 않습니다.

token 모듈의 모든 상수는 :mod:`!tokenize`에서 또한 export됩니다.

토큰화 프로세스를 역전시키는 또 다른 함수가 제공됩니다. 이것은 스크립트를 토큰화하고, 토큰 스트림을 수정한 후, 수정된 스크립트를 다시 쓰는 도구를 만드는 데 유용합니다.

tokenize.untokenize(iterable)

토큰을 파이썬 소스 코드로 역 변환합니다. iterable은 최소한 토큰 유형과 토큰 문자열의 두 요소가 있는 시퀀스를 반환해야 합니다. 추가 시퀀스 요소는 무시됩니다.

결과는 다시 토큰화하면 입력과 일치함이 보장되어, 변환은 무손실이고 왕복이 보장됩니다. 보증은 토큰 유형과 토큰 문자열에만 적용되어, 토큰 간의 간격(열 위치)은 변경될 수 있습니다.

tokenize() 에 의해 출력되는 첫 번째 토큰 시퀀스인 ENCODING 토큰을 사용하여 인코딩된 바이트열을 반환합니다. 입력에 인코딩 토큰이 없으면, 대신 str을 반환합니다.

tokenize()는 토큰화하는 소스 파일의 인코딩을 감지해야 합니다. 이 작업을 수행하는 데 사용되는 함수를 사용할 수 있습니다:

tokenize.detect_encoding(readline)

detect_encoding() 함수는 파이썬 소스 파일을 디코딩할 때 사용해야 하는 인코딩을 감지하는 데 사용됩니다. tokenize() 제너레이터와 같은 방식으로, 하나의 인자 readline을 요구합니다.

readline을 최대 두 번 호출하고, 사용된 인코딩(문자열로)과 읽은 줄들(바이트열에서 디코드 되지 않습니다)의 리스트를 반환합니다.

PEP 263에 지정된 대로 UTF-8 BOM이나 인코딩 쿠키의 존재로부터 인코딩을 검색합니다. BOM과 쿠키가 모두 있지만 서로 일치하지 않으면 SyntaxError가 발생합니다. BOM이 발견되면, 'utf-8-sig'가 인코딩으로 반환됩니다.

인코딩이 지정되지 않으면, 기본값인 'utf-8'이 반환됩니다.

open()을 사용하여 파이썬 소스 파일을 여십시오: detect_encoding()을 사용하여 파일 인코딩을 감지합니다.

tokenize.open(filename)

detect_encoding()에 의해 감지된 인코딩을 사용하여 읽기 전용 모드로 파일을 엽니다.

Added in version 3.2.

exception tokenize.TokenError

여러 줄로 나눌 수 있는 독스트링이나 표현식이 파일의 어디에서도 완료되지 않을 때 발생합니다, 예를 들어:

"""Beginning of
docstring

또는:

[1,
 2,
 3

명령줄 사용법

Added in version 3.3.

tokenize 모듈은 명령줄에서 스크립트로 실행될 수 있습니다. 다음과 같이 간단합니다:

python -m tokenize [-e] [filename.py]

허용되는 옵션은 다음과 같습니다:

-h, --help

이 도움말 메시지를 표시하고 종료합니다

-e, --exact

정확한 유형(exact_type)을 사용하여 토큰 이름을 표시합니다

filename.py가 지정되면 그 내용은 표준출력(stdout)으로 토큰화됩니다. 그렇지 않으면, 표준입력(stdin)에 대해 토큰화가 수행됩니다.

Added in version 3.15: 출력은 기본적으로 색상이 적용되며, :ref:`environment variables <using-on-controlling-color>`를 사용하여 제어할 수 있습니다.

예제

float 리터럴을 Decimal 객체로 변환하는 스크립트 재 작성기의 예제:

from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP
from io import BytesIO

def decistmt(s):
    """문장 문자열에 있는 float를 Decimal로 치환합니다.

    >>> from decimal import Decimal
    >>> s = 'print(+21.3e-5*-.1234/81.7)'
    >>> decistmt(s)
    "print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"

    지수 형식은 플랫폼 C 라이브러리에서 상속됩니다. 알려진 경우는 "e-007" (윈도우) 와 "e-07"
    (윈도우 외) 입니다. 우리는 단지 12자리 숫자를 보여주고 있고, 13번째 숫자는 5에 가깝지
    않으므로, 출력의 나머지 부분은 플랫폼 독립적이어야 합니다.

    >>> exec(s)  #doctest: +ELLIPSIS
    -3.21716034272e-0...7

    Decimal을 사용한 계산의 결과는 모든 플랫폼에서 같아야 합니다.

    >>> exec(decistmt(s))
    -3.217160342717258261933904529E-7
    """
    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')

명령 줄에서 토큰화하는 예제. 스크립트:

def say_hello():
    print("Hello, World!")

say_hello()

는 다음 출력으로 토큰화됩니다. 여기서 첫 번째 열은 토큰이 발견된 줄/열 좌표의 범위이고, 두 번째 열은 토큰의 이름이며, 마지막 열은 토큰의 값입니다 (있다면):

$ python -m tokenize hello.py
0,0-0,0:            ENCODING       'utf-8'
1,0-1,3:            NAME           'def'
1,4-1,13:           NAME           'say_hello'
1,13-1,14:          OP             '('
1,14-1,15:          OP             ')'
1,15-1,16:          OP             ':'
1,16-1,17:          NEWLINE        '\n'
2,0-2,4:            INDENT         '    '
2,4-2,9:            NAME           'print'
2,9-2,10:           OP             '('
2,10-2,25:          STRING         '"Hello, World!"'
2,25-2,26:          OP             ')'
2,26-2,27:          NEWLINE        '\n'
3,0-3,1:            NL             '\n'
4,0-4,0:            DEDENT         ''
4,0-4,9:            NAME           'say_hello'
4,9-4,10:           OP             '('
4,10-4,11:          OP             ')'
4,11-4,12:          NEWLINE        '\n'
5,0-5,0:            ENDMARKER      ''

정확한 토큰 유형 이름은 -e 옵션을 사용하여 표시할 수 있습니다:

0,0-0,0:            ENCODING       'utf-8'
1,0-1,3:            NAME           'def'
1,4-1,13:           NAME           'say_hello'
1,13-1,14:          LPAR           '('
1,14-1,15:          RPAR           ')'
1,15-1,16:          COLON          ':'
1,16-1,17:          NEWLINE        '\n'
2,0-2,4:            INDENT         '    '
2,4-2,9:            NAME           'print'
2,9-2,10:           LPAR           '('
2,10-2,25:          STRING         '"Hello, World!"'
2,25-2,26:          RPAR           ')'
2,26-2,27:          NEWLINE        '\n'
3,0-3,1:            NL             '\n'
4,0-4,0:            DEDENT         ''
4,0-4,9:            NAME           'say_hello'
4,9-4,10:           LPAR           '('
4,10-4,11:          RPAR           ')'
4,11-4,12:          NEWLINE        '\n'
5,0-5,0:            ENDMARKER      ''

generate_tokens()로 바이트열 대신 유니코드 문자열을 읽는, 프로그래밍 방식으로 파일을 토큰화하는 예:

import tokenize

with tokenize.open('hello.py') as f:
    tokens = tokenize.generate_tokens(f.readline)
    for token in tokens:
        print(token)

또는 tokenize()로 직접 바이트열을 읽는 예:

import tokenize

with open('hello.py', 'rb') as f:
    tokens = tokenize.tokenize(f.readline)
    for token in tokens:
        print(token)