解析Python文件并计算所选函数

解析Python文件并计算所选函数,python,parsing,abstract-syntax-tree,Python,Parsing,Abstract Syntax Tree,我有一个包含几个python函数的文件,每个函数都有一些语句 def func1(): codeX... def func2(): codeY... codeX和codeY可以是多个语句。我希望能够解析文件,按名称查找函数,然后计算该函数中的代码 使用ast模块,我可以解析文件,找到FunctionDef对象,并获得Stmt对象的列表,但是如何将其转换为可以传递给eval的字节码呢?我应该使用编译模块还是解析器模块 基本上,函数def只用于创建单独的代码块。我希望能够获取给定名

我有一个包含几个python函数的文件,每个函数都有一些语句

def func1():
    codeX...
def func2():
    codeY...
codeX和codeY可以是多个语句。我希望能够解析文件,按名称查找函数,然后计算该函数中的代码

使用ast模块,我可以解析文件,找到FunctionDef对象,并获得Stmt对象的列表,但是如何将其转换为可以传递给eval的字节码呢?我应该使用编译模块还是解析器模块

基本上,函数def只用于创建单独的代码块。我希望能够获取给定名称的任何代码块,然后在eval中执行该代码(提供我自己的本地/全局范围对象)。如果有比我描述的更好的方法,那也会很有帮助


谢谢

如果您使用的是Python 2.6或更高版本,那么函数除了接受源代码外还接受AST对象

>>> import ast
>>> a = ast.parse("print('hello world')")
>>> x = compile(a, "(none)", "exec")
>>> eval(x)
hello world
这些模块都已为Python3重新安排

我希望能够获取给定名称的任何代码块,然后执行该代码。。。(提供我自己的本地/全局范围对象)

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

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
这看起来很难看,因为它是。完全依赖全局变量的函数并不是最好的主意。

使用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文档中的语法:。顶级语句必须是模块、交互式或表达式,因此需要将函数def封装在其中一个语句中。

eval采用python代码,而不是字节代码。看起来您在这里需要的可能是
exec
而不是
eval
,但无论哪种方式,它们都需要python代码。听起来你差不多到了。为什么?为什么不直接导入Python文件并调用函数?@Lennart在下面看到我对S.Lott的评论,但是如果func1()访问的内容不在默认本地范围内,该怎么办?例如,假设func1()访问一个名为“Direction”的变量。“方向”不在本地或全局范围内。它存储在某个类的数据结构中。我打算用函数所需的数据填充作用域,而不是让函数必须知道特定数据段的位置。@Neal:您应该在这个脚本中输入“Direction=Someclass.somevalue”来“用数据填充作用域”,该数据“存储在某个类的数据结构中”.@S.Lott我想我试图做的另一件事是消除除所需内容之外的任何内容的访问。例如,如果从类方法中调用func1(),则func1()可以访问变量self。我想创建一种沙盒作用域。“func1()可以访问变量self”?怎么用?“我想创建一种沙盒作用域。”这就是脚本。如果
func1()
依赖于其他内容,则编译和
eval()
不会更改依赖项。这些依赖项位于
func1()
的主体中
func1()可以访问变量self
我很确定这不是真的如果我使用ast.parse,然后搜索FuncitonDef对象,并将该对象传递给编译,我会得到一个类型错误。compile似乎只适用于顶级模块ast对象。@Neal:您可能必须对
compile()
函数使用不同的模式标志,或者使用
exec
而不是
eval()
。Python运行时编译器有点挑剔,需要一些实验才能让它完成您想要它做的事情。