tokenize
— Tokenizer för Python-källor¶
Källkod: Lib/tokenize.py
Modulen tokenize
tillhandahåller en lexikal skanner för Python-källkod, implementerad i Python. Skannern i den här modulen returnerar även kommentarer som tokens, vilket gör den användbar för att implementera ”pretty-printers”, inklusive färgläggare för skärmvisning.
För att förenkla hanteringen av tokenflöden, returneras alla operator och delimiter tokens och Ellipsis
med den generiska OP
token-typen. Den exakta typen kan bestämmas genom att kontrollera egenskapen exact_type
på named tuple som returneras från tokenize.tokenize()
.
Varning
Observera att funktionerna i den här modulen endast är utformade för att analysera syntaktiskt giltig Python-kod (kod som inte ger utslag när den analyseras med ast.parse()
). Beteendet hos funktionerna i den här modulen är odefinierat när de tillhandahåller ogiltig Python-kod och det kan ändras när som helst.
Tokenisering av inmatning¶
Den primära ingångspunkten är en generator:
- tokenize.tokenize(readline)¶
Generatorn
tokenize()
kräver ett argument, readline, som måste vara ett anropbart objekt som ger samma gränssnitt som metodenio.IOBase.readline()
för filobjekt. Varje anrop till funktionen bör returnera en rad indata som bytes.Generatorn producerar 5-tupler med dessa medlemmar: token-typen; token-strängen; en 2-tupel
(srow, scol)
av ints som anger raden och kolumnen där token börjar i källan; en 2-tupel(erow, ecol)
av ints som anger raden och kolumnen där token slutar i källan; och raden där token hittades. Den rad som skickas (den sista tupeln) är den fysiska raden. Tupeln 5 returneras som en named tuple med fältnamnen:type string start end line
.Den returnerade named tuple har en ytterligare egenskap med namnet
exact_type
som innehåller den exakta operatortypen förOP
-tokens. För alla andra token-typer ärexact_type
lika med den namngivna tupelns fälttype
.Ändrad i version 3.1: Lagt till stöd för namngivna tupler.
Ändrad i version 3.3: Lagt till stöd för
exact_type
.tokenize()
bestämmer källkodningen för filen genom att leta efter en UTF-8 BOM eller kodningskaka, enligt PEP 263.
- tokenize.generate_tokens(readline)¶
Tokenisera en källa som läser unicode-strängar istället för bytes.
Precis som
tokenize()
är argumentet readline en callable som returnerar en enda rad med indata. Mengenerate_tokens()
förväntar sig att readline returnerar ett str-objekt istället för bytes.Resultatet är en iterator som ger namngivna tupler, precis som
tokenize()
. Det ger inte enENCODING
-token.
Alla konstanter från modulen token
exporteras också från tokenize
.
En annan funktion finns för att vända tokeniseringsprocessen. Detta är användbart för att skapa verktyg som tokeniserar ett skript, modifierar tokenflödet och skriver tillbaka det modifierade skriptet.
- tokenize.untokenize(iterable)¶
Konverterar tokens tillbaka till Python-källkod. iterable måste returnera sekvenser med minst två element, token-typen och token-strängen. Eventuella ytterligare sekvenselement ignoreras.
Resultatet garanteras att tokeniseras tillbaka för att matcha indata så att konverteringen är förlustfri och rundresor garanteras. Garantin gäller endast för token-typen och token-strängen eftersom avståndet mellan tokens (kolumnpositioner) kan ändras.
Den returnerar bytes, kodade med
ENCODING
-token, som är den första tokensekvensen som matas ut avtokenize()
. Om det inte finns någon kodningstoken i indata returneras en str istället.
tokenize()
behöver upptäcka kodningen av källfiler som den tokeniserar. Funktionen som den använder för att göra detta är tillgänglig:
- tokenize.detect_encoding(readline)¶
Funktionen
detect_encoding()
används för att upptäcka den kodning som ska användas för att avkoda en Python-källfil. Den kräver ett argument, readline, på samma sätt som generatorntokenize()
.Den kommer att anropa readline högst två gånger och returnera den kodning som använts (som en sträng) och en lista över alla rader (som inte avkodats från bytes) som den har läst in.
Den detekterar kodningen från närvaron av en UTF-8 BOM eller en kodningskaka enligt specifikationen i PEP 263. Om både en BOM och en cookie finns, men är oense, kommer ett
SyntaxError
att uppstå. Observera att om BOM hittas, kommer'utf-8-sig'
att returneras som kodning.Om ingen kodning anges kommer standardvärdet
'utf-8'
att returneras.Använd
open()
för att öppna Python-källfiler: den använderdetect_encoding()
för att upptäcka filkodningen.
- tokenize.open(filename)¶
Öppna en fil i skrivskyddat läge med hjälp av den kodning som upptäcktes av
detect_encoding()
.Tillagd i version 3.2.
- exception tokenize.TokenError¶
Utlöses när antingen en dokumentsträng eller ett uttryck som kan vara uppdelat på flera rader inte avslutas någonstans i filen, till exempel:
"""Början av dokumentsträng
eller:
[1, 2, 3
Användning av kommandoraden¶
Tillagd i version 3.3.
Modulen tokenize
kan köras som ett skript från kommandoraden. Det är så enkelt som att:
python -m tokenize [-e] [filnamn.py]
Följande alternativ accepteras:
- -h, --help¶
visa detta hjälpmeddelande och avsluta
- -e, --exact¶
visa tokennamn med exakt typ
Om filnamn.py
anges tokeniseras dess innehåll till stdout. I annat fall utförs tokenisering på stdin.
Exempel¶
Exempel på en script rewriter som omvandlar float-literaler till Decimal-objekt:
from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP
from io import BytesIO
def decistmt(s):
"""Substitute Decimals for floats in a string of statements.
>>> from decimal import Decimal
>>> s = 'print(+21.3e-5*-.1234/81.7)'
>>> decistmt(s)
"print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"
The format of the exponent is inherited from the platform C library.
Known cases are "e-007" (Windows) and "e-07" (not Windows). Since
we're only showing 12 digits, and the 13th isn't close to 5, the
rest of the output should be platform-independent.
>>> exec(s) #doctest: +ELLIPSIS
-3.21716034272e-0...7
Output from calculations with Decimal should be identical across all
platforms.
>>> exec(decistmt(s))
-3.217160342717258261933904529E-7
"""
result = []
g = tokenize(BytesIO(s.encode('utf-8')).readline) # tokenize the string
for toknum, tokval, _, _, _ in g:
if toknum == NUMBER and '.' in tokval: # replace NUMBER tokens
result.extend([
(NAME, 'Decimal'),
(OP, '('),
(STRING, repr(tokval)),
(OP, ')')
])
else:
result.append((toknum, tokval))
return untokenize(result).decode('utf-8')
Exempel på tokenisering från kommandoraden. Skriptet:
def say_hello():
print("Hello, World!")
say_hello()
kommer att tokeniseras till följande utdata där den första kolumnen är intervallet för rad- / kolumnkoordinaterna där token hittas, den andra kolumnen är namnet på token och den sista kolumnen är värdet på token (om någon)
$ 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 ''
De exakta namnen på token-typerna kan visas med hjälp av alternativet -e
:
$ python -m tokenize -e 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: 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 ''
Exempel på tokenisering av en fil programmatiskt, läsning av unicode-strängar istället för bytes med generate_tokens()
:
import tokenize
with tokenize.open('hello.py') as f:
tokens = tokenize.generate_tokens(f.readline)
for token in tokens:
print(token)
Eller läsa bytes direkt med tokenize()
:
import tokenize
with open('hello.py', 'rb') as f:
tokens = tokenize.tokenize(f.readline)
for token in tokens:
print(token)