这可能很奇怪,但我正在寻找一种方法来自动获取python脚本中的所有变量和方法。
例如,
prefix_users_sessions
我想要
a = 1
b = 2
c = 3
myList = range(10)
def someMethod(x):
something = do_something()
return something
f = someMethod(b)
print f
这是一个示范性示例,我想为更大的脚本执行此操作。
答案 0 :(得分:15)
ast
module可以相当轻松地完成此操作。如果我们假设源存储在名为source
的变量中(可以从文件中读取):
import ast
root = ast.parse(source)
names = sorted({node.id for node in ast.walk(root) if isinstance(node, ast.Name)})
失去了获得统一和友好的显示顺序的命令,但如果你不需要唯一性但想要排序,你可以使用列表理解或生成器表达而不是集合理解。结果list
为:
['a', 'b', 'c', 'do_something', 'f', 'myList', 'range', 'someMethod', 'something', 'x']
与到目前为止发布的其他解决方案不同,它会递归到类和函数中以获取其中使用的名称,并且不需要您导入要检查的模块或类,也不需要您实现递归处理自己;任何语法上有效的Python代码都可以使用。
奇怪的是,在Python 3(替换有效的print
函数调用)上,您得到:
['a', 'b', 'c', 'do_something', 'f', 'myList', 'print', 'range', 'someMethod', 'something']
添加了print
(正如预期的那样;它现在是名称,而不是关键字语句),但省略了x
。你没有要求x
(someMethod
收到的论点),而且这并没有在Python 3上产生它。函数原型中的名字似乎没有创建{{1那个节点,去图。您可以从ast.Name
ast.FunctionDef
中每个条目的arg
属性中提取list
节点中的信息,但它可能仍然不全面;我怀疑其他定义相关名称可能会被遗漏,例如在具有继承的类声明中。您需要使用一些示例来确保您检查所有内容(假设您需要node.args.args
等内容并希望使用Python 3)。
那就是说,如果引用它,x
会很好地显示出来;如果您将其传递给x
或以任何方式使用它,除了接收和丢弃它之外,它都会显示出来。
您还可以通过将测试扩展到:
来仅处理分配给,未使用的名称(以排除do_something
,do_something
)
range
但是这也会降低names = sorted({node.id for node in ast.walk(root) if isinstance(node, ast.Name) and not isinstance(node.ctx, ast.Load)})
(在Py2和Py3中),因为定义本身并不会产生someMethod
,只有使用它才会产生ast.Name
。同样,您需要深入研究ast.Node
,ast.FunctionDef
等的ast.ClassDef
内部,以获取不是{{1}的名称直接编辑。
答案 1 :(得分:3)
python导入了很多变量,因此您将获得一个长列表,但vars()
将起作用。
a = 1
b = 2
c = 3
myList = range(10)
def someMethod(x):
something = 4
return something
f = someMethod(b)
print vars()
终端:
$ python temp.py
{'a': 1, 'c': 3, 'b': 2, 'myList': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 'f': 4, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'temp.py', '__package__': None, 'someMethod': <function someMethod at 0x10759b488>, '__name__': '__main__', '__doc__': None}
修改强>
您可以通过检查变量类型来清理它
import types
all_vars = dict(vars())
for var_name, var in all_vars.iteritems():
if type(var) not in [types.ModuleType, types.FunctionType] and not var_name.startswith("_"):
print var_name
终端:
$ python temp.py
a
c
b
myList
f
答案 2 :(得分:2)
您可以使用globals()
函数获取模块中的所有全局名称,并且由于python默认情况下有一些全局名称,例如__builtins__
,您可以将它们转义:
由于globals()
返回的字典包含名称和值,而内置名称的格式类似__builtins__
,您可以过滤它们:
>>> print([var for var in globals().keys() if '__' not in var])
['someMethod', 'c', 'b', 'a', 'myList']
但请注意,它不会像something
那样为您提供函数内的本地名称。为此,您可以看到inspect
模块https://docs.python.org/3/library/inspect.html#inspect.getmembers
答案 3 :(得分:1)
您可以使用内置的dir()。假设您将文件保存为test.py.您可以执行以下操作:
>>> import test
>>> dir(test)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'b', 'c', 'f', 'myList', 'someMethod']
>>>