如何获取脚本中使用的所有变量和方法名称 [英] How to get all variable and method names used in script

查看:29
本文介绍了如何获取脚本中使用的所有变量和方法名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能很奇怪,但我正在寻找一种方法来自动获取 python 脚本中的所有变量和方法.

It can be weird but I am looking for a way to get automatically all variables and method within a python script.

例如

a = 1
b = 2
c = 3
myList = range(10)

def someMethod(x): 
    something = do_something()
    return something

f = someMethod(b)

print f

我想得到

a, b, c, someMethod, something, f

这是一个演示示例,我想为更大的脚本执行此操作.

This is a demonstrative example, I want to do this for a much bigger script.

推荐答案

ast 模块 可以很容易地做到这一点.如果我们假设源存储在名为 source 的变量中(可以从文件中读取):

The ast module can do this fairly easily. If we assume the source is stored in a variable named source (could be read from a file):

import ast

root = ast.parse(source)
names = sorted({node.id for node in ast.walk(root) if isinstance(node, ast.Name)})

这失去了获得唯一性和友好显示顺序的排序,但是如果您不需要唯一性但想要排序,则可以使用列表推导式或生成器表达式而不是集合推导式.结果 list 是:

That loses ordering to gain uniquification and friendly display order, but you could just use a list comprehension or generator expression instead of a set comprehension if you don't need uniqueness but want ordering. The resulting list is:

['a', 'b', 'c', 'do_something', 'f', 'myList', 'range', 'someMethod', 'something', 'x']

与目前发布的其他解决方案不同,这将递归到类和函数中以获取其中使用的名称,并且不需要您导入模块或类进行检查,也不需要您实现递归处理你自己;任何语法上有效的 Python 代码都可以使用.

Unlike the other solutions posted so far, this will recurse into classes and functions to get the names used inside them, and doesn't require you to import the module or class to check, nor does it require you to implement recursive processing yourself; any syntactically valid Python code will work.

奇怪的是,在 Python 3 上(替换一个有效的 print 函数调用),你得到:

Oddly, on Python 3 (substituting a valid print function call), you get:

 ['a', 'b', 'c', 'do_something', 'f', 'myList', 'print', 'range', 'someMethod', 'something']

它添加了 print(正如预期的那样;它现在是一个名称,而不是关键字语句),但省略了 x.您没有要求 x(someMethod 收到的参数),这不会在 Python 3 上生成它.函数原型中的名称似乎不会创建 ast.Name 节点在那里,去图.您可以从 list node.args 中每个条目的 arg 属性中从 ast.FunctionDef 节点中提取该信息.args,但它可能仍然不全面;我怀疑可能会遗漏其他与定义相关的名称,例如在具有继承的类声明中.您需要查看一些示例以确保您检查了所有内容(假设您想要像 x 这样的东西并且想要在 Python 3 上工作).

which adds print (as expected; it's a name now, not a keyword statement), but omits x. You didn't ask for x (the argument received by someMethod), and this doesn't produce it on Python 3. Names in function prototypes appear to not create a ast.Name node there, go figure. You can pull that info out of the ast.FunctionDef node from the arg attribute of each entry in the list node.args.args, but it's probably still not comprehensive; I suspect other definition related names might be missed, e.g. in class declarations with inheritance. You'd need to poke around with some examples to make sure you're checking everything (assuming you want stuff like x and want to work on Python 3).

也就是说,如果您引用 x 就会显示得很好;如果你把它传递给 do_something 或者以任何方式使用它,除了接收和丢弃它,它会显示出来.

That said, x would show up just fine if you referenced it; if you passed it to do_something or used it in any way besides receiving and discarding it, it would show up.

您还可以通过将测试扩展到:

You can also make an effort to only handle names assigned to, not used (to exclude do_something, range) by extending the test to:

names = sorted({node.id for node in ast.walk(root) if isinstance(node, ast.Name) and not isinstance(node.ctx, ast.Load)})

但这也会删除 someMethod(在 Py2 和 Py3 中),因为定义本身不会产生 ast.Name,只有使用它才会产生.因此,您必须再次深入研究 ast.FunctionDefast.ClassDef 等的 ast.Node 内部结构.获取不是直接walk-ed 的名称.

But that will also drop someMethod (in both Py2 and Py3) because the definition itself doesn't produce an ast.Name, only the use of it does. So again, you'd have to delve a little deeper into the ast.Node internals for ast.FunctionDef, ast.ClassDef, etc. to get the names that aren't walk-ed directly.

这篇关于如何获取脚本中使用的所有变量和方法名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆