跳到主要内容

Python exec() 函数

exec() 方法执行动态创建的程序,该程序可以是字符串或代码对象。

示例

program = 'a = 5\nb=10\nprint("总和 =", a+b)'
exec(program)

# 输出:总和 = 15

exec() 语法

exec() 的语法是:

exec(object, globals, locals)

exec() 参数

exec() 方法接受三个参数:

  • object - 字符串或代码对象
  • globals (可选)- 一个字典
  • locals (可选)- 映射对象(通常是字典)

exec() 返回值

exec() 方法不返回任何值。

示例 1:Python exec()

program = 'a = 5\nb=10\nprint("总和 =", a+b)'
exec(program)

输出

总和 = 15

在上面的示例中,我们将字符串对象 program 传递给了 exec() 方法。

该方法执行对象方法中的 Python 代码,并产生输出 总和 = 15

示例 2:exec() 使用单行程序输入

# 获取整个程序作为输入
program = input('输入一个程序:')

# 执行程序
exec(program)

输出

输入一个程序:[print(item) for item in [1, 2, 3]]
1
2
3

在上面的示例中,我们提供了代码;

print(item) for item in [1, 2, 3]

作为输入值。

这里,我们使用了 exec() 方法来执行包含用户输入代码的程序对象。

注意:当你使用带有 OS 模块的 exec() 方法时,需要小心。这是因为当你在输入中使用 os.system('rm -rf *') 代码时,可能会意外地更改和删除文件。

示例 3:exec() 使用多行输入程序

我们可以使用 \n 将多行输入程序传递给 exec() 方法,但我们需要先使用 compile() 方法来编译程序。

# 获取多行程序作为输入
program = input('输入一个程序:')

# 在执行模式下编译程序
b = compile(program, 'something', 'exec')

# 执行程序
exec(b)

输出

输入一个程序:'a = 5\nb=10\nprint("总和 =", a+b)'
90

在上述示例中,我们将多行程序作为参数传递给了 exec() 方法。

但在此之前,我们需要使用 compile() 方法编译这个程序。

示例 4:使用 exec() 检查可用代码

检查你可以与 exec() 方法一起使用的方法和变量是个好主意。你可以借助 dir() 方法来完成这个操作。

# 导入 math 库的所有方法
from math import *

# 检查可用的方法
exec('print(dir())')

输出

['In', 'Out', '_', '__', '___', '__builtin__', '__builtins__', '__name__', ….]

示例 5:在 exec() 中阻止不必要的方法和变量

大多数时候,我们并不需要 exec() 中的所有方法和变量。

我们可以通过向 exec() 方法传递可选的 globals 和 locals 参数来阻止这些不必要的方法和变量。

有关更多信息,请查看 locals()globals()

# 导入 math 库的方法
from math import *

# 使用 cbrt() 方法
mycode='''a = cbrt(9)
print(a)'''

# 空字典(全局参数)以限制 cbrt() 方法
exec(mycode, {})

输出

NameError: name 'cbrt' is not defined

在上述示例中,尽管我们已经导入了整个 math 库,但我们限制了 exec()cbrt() 方法的使用。

这就是为什么我们得到输出 NameError: name 'cbrt' is not defined

示例 6:在 exec() 中使用必要的方法和变量

我们也可以使必要的方法和变量可供 exec() 方法使用。

为此,我们需要向 exec() 传递 locals 字典。

from math import *

# 将全局参数设置为 none
globalsParameter = {'__builtins__' : None}

# 设置本地参数以仅接受 print() 和 dir()
localsParameter = {'print': print, 'dir': dir}

# 打印可访问方法目录
exec('print(dir())', globalsParameter, localsParameter)

输出

['dir', 'print']

在上述示例中,我们用以下代码阻止了所有全局内置方法:

globalsParameter = {'__builtins__' : None}

但是,我们允许两个方法 - print()dir() 可以执行,使用以下代码:

localsParameter = {'print': print, 'dir': dir}

最后,我们将 dir() 方法放入 print() 方法中,然后传递给 exec() 方法以打印可用方法列表。

这里的 globalsParameter 和 localsParameter 是我们用 exec() 方法只打印我们想要访问的方法时使用的可选参数。

推荐阅读