Python中有三个内置函数eval()
、exec()
和compile()
来执行动态代码。这些函数能够从字符串参数中读取Python代码并在运行时执行该代码。但是,使用这些函数时必须小心,因为它们的不当使用可能会导致安全漏洞。
eval()
函数可解析一个字符串表达式,并返回表达式的计算结果。该函数接受可选的globals
和locals
参数,用于指定在编译时使用的全局和局部命名空间。
>>> x = 5
>>> y = 10
>>> eval('x + y')
15
eval()
函数执行的代码是不受限制的,因此请勿使用它来解析未知来源的字符串。eval()
函数中执行负数计算。然而,该实现也可能会导致计划外的代码执行和安全漏洞。exec()
函数也可解析一个字符串表达式,但不返回任何值。该函数同样接受可选的globals
和locals
参数。
>>> program = 'print("Hello, World!")'
>>> exec(program)
Hello, World!
compile()
是一个内置函数,将Python源代码编译为字节代码或AST对象,不会执行该代码。编译后的代码通过eval()
或exec()
函数执行。它的用法如下:
compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
该函数共有6个参数:
source
- 必需,要被编译的源代码字符串,或者以\n
分割的代码行的元组、列表。还可以传入AST对象。filename
- 必需,代码所在文件名称,如果代码不是从文件读取,则可以使用任何名称。mode
- 必需,指定编译代码的种类。取值为exec
表示代码将被编译为可执行的代码,取值为eval
表示代码将被编译为一个单一的表达式,如果代码中包含换行,则会抛出语法错误,取值为singe
表示代码预期来自单个交互输入,需要使用类似于REPL的方式来执行该代码。flags
- 可选,可以用来声明变量全局命名空间和本地命名空间(与exec()
中的globals
和locals
参数相同)。同时,还可以使用其他标志,例如与调试相关的标志。dont_inherit
- 可选,默认值为False
,指定在复制其父级的标志和作用域(模块或类)时是否跳过指定模块或类。当编写一系列嵌套的类或函数时,这个选项非常有用。optimize
- 可选,默认值为-1
,可以通过0、1或2来指定优化级别。优化等级越高,执行的代码速度越快,但是编译过程的时间也会更长。>>> source = """
... def say_hello(name):
... print("Hello, " + name + "!")
...
... say_hello("World")
... """
>>> code = compile(source, "<string>", "exec")
>>> exec(code)
Hello, World!
compile()
时,需要明确了解编译代码的风险。eval()
执行简单的数学表达式下面是如何使用eval()
计算简单的数学表达式的示例:
calculation = input("Enter a calculation: ")
result = eval(calculation)
print("Result:", result)
运行该程序,会提示用户输入一个简单的数学表达式,例如:3 + 4 * 5
,程序将计算结果并打印出来。
compile()
和exec()
编译和执行Python代码下面是如何使用compile()
和exec()
编译和执行Python代码的示例:
code = """
def say_hello(name):
print("Hello, " + name + "!")
"""
compiled_code = compile(code, "<string>", "exec")
exec(compiled_code)
say_hello("World")
运行该程序,将输出Hello, World!
的结果。