令牌化Python源文件时的令牌名称和关键字(在Python中)

时间:2016-05-25 16:50:16

标签: python python-3.x token tokenize

this answer之后,我试图获取Python源文件的所有令牌信息(即令牌的确切名称,值和位置),如下所示。

# Python source file
import os

class Test():
    """
    This class holds latitude, longitude, depth and magnitude data.
    """

    def __init__(self, latitude, longitude, depth, magnitude):
        self.latitude = latitude
        self.longitude = longitude
        self.depth = depth
        self.magnitude = magnitude

    def __str__(self):
        # -1 is for detection of missing data
        depth = self.depth
        if depth == -1:
            depth = 'unknown'

        magnitude = self.magnitude
        if magnitude == -1:
            depth = 'unknown'

        return "M{0}, {1} km, lat {2}\N{DEGREE SIGN} lon {3}\N{DEGREE SIGN}".format(magnitude, depth, self.latitude, self.longitude)

所以,理想,我希望我的输出看起来像:

  •   

    line = 15,column = 9,value ='def',token ='method for method'

  •   

    line = 18,column = 13,value ='if',token ='if statement'

我试试这个

with open(file, 'rb') as f:
    for t in tokenize.tokenize(f.readline):
        print(t.type, t.exact_type)

我得到了这个输出

59 59
57 57
58 58
5 5
1 1
1 1
4 4
58 58
1 1
1 1
53 7
53 8
53 11
(...)

当我尝试这个时

with open(file, 'rb') as f:
    for toknum, tokval, spos, epos, line in tokenize.tokenize(f.readline):
        print(toknum, tokval, spos)

我得到了这个输出

59 utf-8 (0, 0)
57 # Python source file (1, 4)
58 
 (1, 24)
5      (2, 0)
1 import (2, 4)
1 os (2, 11)
4 
 (2, 13)
58 
 (3, 4)
1 class (4, 4)
1 Test (4, 10)
53 ( (4, 14)
53 ) (4, 15)
53 : (4, 16)
(...)

我有兴趣获取文档中提到的 exact_type令牌;即令牌的名称。到目前为止,我只能看到它,如果在我的第一个例子中我打印整个元组t

任何想法如何实现这一目标?

另外,我在网上找不到任何相关的有用示例代码。我可以研究用于在Python中解析/标记Python源文件的任何链接/在线资料吗?

将非常感谢任何简单易用的代码示例。 此外,如果您知道有用的在线资料,其中包含tokenize模块的示例/解释及其方法,那将非常棒。

1 个答案:

答案 0 :(得分:1)

我相信您感兴趣的内容可以通过A bstract语法树来实现;遍历它们 - 特别是那些AST的叶节点,即令牌(参见token模块),它代表您正在寻找的所有值和关键字。

因此,您应该查看astparser模块,而不是tokenize模块。另外,正如文档中所述,Green Tree Snakes在AST的主题上有一些非常好的材料。

为了帮助您入门,这里有一个小例子,它读取python源文件,通过ast解析它并提取类的名称:

import tokenize
import ast

with tokenize.open(source) as sf:  # need the tokenize.open for source files and not a string
    source_file_contents = sf.read()

module = ast.parse(source_file_contents)

class_definitions = []

for node in module.body:
    if isinstance(node, ast.ClassDef):
        class_defs.append(node)
            class_definitions.append(node)

print([class_definition.name for class_definition in class_definitions])

最后,如果你想进入访问AST的节点的方向(即通过ast.NodeVisitor),那么你可以在stackoverflow中找到好的资源,比如{{ 3}}或this