【问题标题】:Find dependencies in a python source/script在 python 源/脚本中查找依赖项
【发布时间】:2012-12-19 10:09:38
【问题描述】:

我有一堆简单的 Python 脚本,带有简单的表达式[1],例如:

C = A+B
D = C * 4

我需要执行它们,但最重要的是我需要知道我依赖的对象是什么;在前一种情况下,对象 AB 是外部依赖项。例如。鉴于我在一个名为 source 的 var 中有以前的代码,我希望能够:

deps = { "A" : 1 , "B": 2}
exec source in deps

所以知道如何构建字典是非常有必要的deps

我潜入了 ast Python 模块,但我不知道。


[1] 简单的数学聚合,在一定程度上 for 个周期,仅此而已。

【问题讨论】:

  • 我猜你可能很顽皮并抓住了前几个 NameErrors
  • 我很顽皮,没有提到我所做的与@JakobBowyer 建议的完全一样;)
  • 一个 AST 是不够的。如果没有完整的 AST、全名解析和认真的数据流分析,除了非常琐碎的脚本之外,您将无法使其工作。因为 Python 是一种动态语言,所以即使是严肃的数据流分析也可能无法提供像样的答案。如果您愿意将“Python”代码限制为非常简单,则可以构建一个可靠的分析器。您的问题是您的用户不会注意您将施加的约束。因此,除非用户只是您,否则您不太可能获得好的结果。
  • 谢谢@IraBaxter,我很清楚你的主张;我已经在考虑数据流解决方案:我正在构建这些脚本的图表...
  • 您需要在“简单”表达式中允许什么的准确描述是什么?没有这个限制,你就得不到任何有用的建议。

标签: python dependencies abstract-syntax-tree


【解决方案1】:

您可以使用标准库中的 tokenize 模块对 Python 源代码进行标记。这将允许您找到脚本中使用的所有变量名称。

现在假设我们将“非依赖”定义为紧接在= 符号之前的任何变量名。然后,根据您的脚本代码的简单程度(请参阅下面的注意事项),您可以通过这种方式确定不是非依赖项的变量名称:

import tokenize
import io
import token
import collections
import keyword

kwset = set(keyword.kwlist)
class Token(collections.namedtuple('Token', 'num val start end line')):
    @property
    def name(self):
        return token.tok_name[self.num]

source = '''
C = A+B
D = C * 4
'''

lastname = None
names = set()
not_dep = set()
for tok in tokenize.generate_tokens(io.BytesIO(source).readline):
    tok = Token(*tok)
    print(tok.name, tok.val)
    if tok.name == 'NAME':
        names.add(tok.val)
        lastname = tok.val
    if tok.name == 'OP' and tok.val == '=':
        not_dep.add(lastname)

print(names)
# set(['A', 'C', 'B', 'D'])
print(not_dep)
# set(['C', 'D'])

deps = dict.fromkeys(names - not_dep - kwset, 1)
print(deps)
# {'A': 1, 'B': 1}

注意事项

  • 如果您的脚本包含非简单语句 分配,然后names 可能会填充不受欢迎的 变量名。例如,

    import numpy
    

    会将'import''numpy' 添加到集合names

  • 如果您的脚本包含使用左手的赋值 侧元组拆包,如

    E, F = 1, 2
    

    那么上面的幼稚代码只会识别出F 不是 依赖。

【讨论】:

  • 非常感谢!这是一个开始;)我想,如果我让我的同事用全部大写的“变量”编写这些脚本,而不是使用单行多重赋值,我可以使用它;)
  • 或者说服你的同事编写可运行的代码来明确依赖关系。也许是一个函数?
  • 此外,就exec source in deps 而言,deps 是否包含非依赖项的变量名称的键并不重要。无论如何,source 重新定义了它们。因此,例如,如果您通过生成随机值以在deps 中使用来进行错误测试,那么如果您对依赖项的定义过于宽泛也没关系。
  • 你说得对,@unutbu:实际上我想使用deps 变量中应该包含的内容来检查变量图中是否存在这些变量(主题变得更广泛。 ...)脚本来自我用 ANTLR 编写的语法转换工具;它们可以(很少)由对这里讨论的主题一无所知的“同事”编辑;)...
  • 感谢 Giupo 对keyword.kwlist 的建议编辑。我已经编辑了我的帖子以包含它。
猜你喜欢
  • 2011-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
  • 2016-05-24
  • 1970-01-01
相关资源
最近更新 更多