解析Python文件并评估选定函数

2 投票
3 回答
3875 浏览
提问于 2025-04-16 09:43

我有一个文件,里面包含了几个Python函数,每个函数都有一些语句。

def func1():
    codeX...
def func2():
    codeY...

codeX和codeY可以有多条语句。我想解析这个文件,通过函数名找到一个函数,然后执行这个函数里的代码。

使用ast模块,我可以解析文件,找到FunctionDef对象,并获取Stmt对象的列表,但我该如何将这些转换成可以传给eval的字节码呢?我应该使用compile模块,还是parser模块呢?

基本上,函数定义只是用来创建独立的代码块。我想根据名字抓取任何代码块,然后在eval中执行这些代码(提供我自己的局部/全局作用域对象)。如果有比我描述的方法更好的做法,那也很有帮助。

谢谢

3 个回答

1

如果你使用的是Python 2.6或更新的版本,那么 compile() 这个函数除了可以接受源代码之外,还可以接受AST对象。

>>> import ast
>>> a = ast.parse("print('hello world')")
>>> x = compile(a, "(none)", "exec")
>>> eval(x)
hello world

这些模块在Python 3中都进行了重新整理。

2

我想要能够根据名称获取任何代码块,然后执行这些代码……(同时提供我自己的本地/全局作用域对象)。

一个简单的解决方案看起来是这样的。这是基于假设这些函数并不都依赖于全局变量。

from  file_that_contains_several_python_functions import *
Direction = some_value
func1()
func2()
func3()

这样做应该正好符合你的需求。

但是,如果你的所有函数都依赖于全局变量——这种设计让人想起1970年代的FORTRAN——那么你就需要做一些稍微复杂的事情。

 from  file_that_contains_several_python_functions import *
 Direction = some_value
 func1( globals() )
 func2( globals() )
 func3( globals() )

而且你必须像这样重写所有使用全局变量的函数。

 def func1( context )
     globals().update( context )
     # Now you have access to all kinds of global variables

这样看起来很丑,因为确实是这样。完全依赖全局变量的函数其实并不是一个好主意。

1

使用 Python 2.6.4:

text = """
def fun1():
    print 'fun1'

def fun2():
    print 'fun2'

"""

import ast
tree = ast.parse(text)
# tree.body[0] contains FunctionDef for fun1, tree.body[1] for fun2

wrapped = ast.Interactive(body=[a.body[1]])
code = compile(wrapped, 'yourfile', 'single')
eval(code)
fun2() # prints 'fun2'

看看 ast 文档中的语法:http://docs.python.org/library/ast.html#abstract-grammar。最顶层的语句必须是模块、交互式或表达式之一,所以你需要把函数定义放在这三者中的一个里面。

撰写回答