tokenize
— Analyseur lexical de Python¶
Code source : Lib/tokenize.py
The tokenize
module provides a lexical scanner for Python source code,
implemented in Python. The scanner in this module returns comments as tokens
as well, making it useful for implementing "pretty-printers", including
colorizers for on-screen displays.
Pour simplifier la gestion de flux de tokens, tous les tokens operator et delimiter, ainsi que les Ellipsis*
sont renvoyés en utilisant le token générique OP
. Le type exact peut être déterminé en vérifiant la propriété exact_type
du named tuple renvoyé par tokenize.tokenize()
.
Analyse Lexicale¶
Le point d'entrée principal est un générateur :
-
tokenize.
tokenize
(readline)¶ Le générateur
tokenize()
prend un argument readline qui doit être un objet appelable exposant la même interface que la méthodeio.IOBase.readline()
des objets fichiers. Chaque appel a la fonction doit renvoyer une ligne sous forme de bytes.The generator produces 5-tuples with these members: the token type; the token string; a 2-tuple
(srow, scol)
of ints specifying the row and column where the token begins in the source; a 2-tuple(erow, ecol)
of ints specifying the row and column where the token ends in the source; and the line on which the token was found. The line passed (the last tuple item) is the physical line. The 5 tuple is returned as a named tuple with the field names:type string start end line
.Le n-uplet nommé a une propriété additionnelle appelée
exact_type
qui contient le type exact de l'opérateur pour les jetonsOP
. Pour tous les autres types de jetons,exact_type
est égal au champtype
du n-uplet nommé.Modifié dans la version 3.1: prise en charge des n-uplets nommés.
Modifié dans la version 3.3: prise en charge de
exact_type
.tokenize()
détermine le codage source du fichier en recherchant une nomenclature UTF-8 ou un cookie d'encodage, selon la PEP 263.
-
tokenize.
generate_tokens
(readline)¶ Tokenize a source reading unicode strings instead of bytes.
Like
tokenize()
, the readline argument is a callable returning a single line of input. However,generate_tokens()
expects readline to return a str object rather than bytes.The result is an iterator yielding named tuples, exactly like
tokenize()
. It does not yield anENCODING
token.
Toutes les constantes du module token
sont également exportées depuis module tokenize
.
Une autre fonction est fournie pour inverser le processus de tokenisation. Ceci est utile pour créer des outils permettant de codifier un script, de modifier le flux de jetons et de réécrire le script modifié.
-
tokenize.
untokenize
(iterable)¶ Convertit les jetons en code source Python. L'iterable doit renvoyer des séquences avec au moins deux éléments, le type de jeton et la chaîne de caractères associée. Tout élément de séquence supplémentaire est ignoré.
Le script reconstruit est renvoyé sous la forme d'une chaîne unique. Le résultat est garanti pour que le jeton corresponde à l'entrée afin que la conversion soit sans perte et que les allers et retours soient assurés. La garantie ne s'applique qu'au type de jeton et à la chaîne de jetons car l'espacement entre les jetons (positions des colonnes) peut changer.
It returns bytes, encoded using the
ENCODING
token, which is the first token sequence output bytokenize()
. If there is no encoding token in the input, it returns a str instead.
tokenize()
a besoin de détecter le codage des fichiers sources qu'il code. La fonction utilisée pour cela est disponible :
-
tokenize.
detect_encoding
(readline)¶ La fonction
detect_encoding()
est utilisée pour détecter l'encodage à utiliser pour décoder un fichier source Python. Il nécessite un seul argument, readline, de la même manière que le générateurtokenize()
.Il appelle readline au maximum deux fois et renvoie le codage utilisé (sous forme de chaîne) et une liste de toutes les lignes (non décodées à partir des octets) dans lesquelles il a été lu.
Il détecte l'encodage par la présence d'une marqueur UTF-8 (BOM) ou d'un cookie de codage, comme spécifié dans la PEP 263. Si un BOM et un cookie sont présents, mais en désaccord, un
SyntaxError
sera levée. Notez que si le BOM est trouvé,'utf-8-sig'
sera renvoyé comme encodage.Si aucun codage n'est spécifié, la valeur par défaut,
'utf-8'
, sera renvoyée.Utilisez
open()
pour ouvrir les fichiers source Python : ça utilisedetect_encoding()
pour détecter le codage du fichier.
-
tokenize.
open
(filename)¶ Ouvre un fichier en mode lecture seule en utilisant l'encodage détecté par
dectect_encoding()
.Nouveau dans la version 3.2.
-
exception
tokenize.
TokenError
¶ Déclenché lorsque soit une docstring soit une expression qui pourrait être divisée sur plusieurs lignes n'est pas complété dans le fichier, par exemple :
"""Beginning of docstring
ou :
[1, 2, 3
Notez que les chaînes à simple guillemet non fermés ne provoquent pas le déclenchement d'une erreur. Ils sont tokenisés comme ERRORTOKEN
, suivi de la tokenisation de leur contenu.
Utilisation en ligne de commande.¶
Nouveau dans la version 3.3.
Le module tokenize
peut être exécuté en tant que script à partir de la ligne de commande. C'est aussi simple que :
python -m tokenize [-e] [filename.py]
Les options suivantes sont acceptées :
-
-h
,
--help
¶
Montre ce message d'aide et quitte
-
-e
,
--exact
¶
Affiche les noms de jetons en utilisant le même type.
Si filename.py
est spécifié, son contenu est tokenisé vers stdout. Sinon, la tokenisation est effectuée sur ce qui est fourni sur stdin.
Exemples¶
Exemple d'un script qui transforme les littéraux de type float en type Decimal :
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')
Exemple de tokenisation à partir de la ligne de commande. Le script :
def say_hello():
print("Hello, World!")
say_hello()
sera tokenisé à la sortie suivante où la première colonne est la plage des coordonnées de la ligne/colonne où se trouve le jeton, la deuxième colonne est le nom du jeton, et la dernière colonne est la valeur du jeton (le cas échéant)
$ 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 ''
Les noms exacts des types de jeton peuvent être affichés en utilisant l’option : -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 ''
Example of tokenizing a file programmatically, reading unicode
strings instead of bytes with generate_tokens()
:
import tokenize
with tokenize.open('hello.py') as f:
tokens = tokenize.generate_tokens(f.readline)
for token in tokens:
print(token)
Or reading bytes directly with tokenize()
:
import tokenize
with open('hello.py', 'rb') as f:
tokens = tokenize.tokenize(f.readline)
for token in tokens:
print(token)