Python exec() 函数用法

2023-09-17 22:27:39

exec() 方法执行作为字符串或代码对象传递的 Python 代码块。该字符串被解析为 Python 语句,然后执行。

语法:

exec(object, globals, locals)

参数:

对象
  1. :(必需)字符串或代码对象。
  2. globals:(可选)包含全局变量的字典。
  3. locals:(可选)包含局部变量的字典。

返回值:

没有。

下面的示例演示简单的exec()方法。

exec('print("Hello World")')

输出:

Hello World

在上面的示例中,'print("Hello World")'字符串被解析为 Python 语句并执行。

字符串可以是多行代码字符串,其中每行将被视为一个语句,如下所示:

mycode='''a=5
b=4
print('axb=', a*b)'''
exec(mycode)

输出:

axb= 20

传递给 exec() 方法的代码也可以使用 input() 函数获取用户输入。

code = input("Enter Python Expression: ")
exec(code)

输出:

Enter Python Expression: [print(x**2) for x in [1, 2, 3,4,5]]
1
4
9
16
25

默认情况下,exec()函数可以执行内置函数。例如,下面执行abs()函数。

exec('print(abs(-9))')

输出:

9

下面的示例显示了在未导入任何模块时可用于exec()的所有函数。

exec('print(dir())')

输出:

['annotations', 'builtins', 'doc', 'loader', 'name', 'package', 'spec']

您可以在 exec() 方法中传递的代码字符串中导入模块并使用该模块的函数,如下所示。

mycode='''from math import *
a = sqrt(9)
print(a)'''
exec(mycode)

输出:

3.0

如果在调用 exec() 方法(例如 math 模块)之前导入模块,则数学模块的所有方法都可以在 exec() 方法中使用。

from math import *
exec('print(dir())')

输出:

['annotations', 'builtins', 'doc', 'loader', 'name', 'package', 'spec', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

然后,您可以在exec()中执行导入模块的函数,而无需在代码字符串中包含 import 语句。

from math import *
mycode='''a = sqrt(9)
print(a)'''
exec(mycode)

输出:

3.0

默认情况下,可以在 exec() 方法中使用所有本地、内置和导入模块的函数。使用 globals 参数指定可由 exec() 函数执行的全局、导入模块或内置函数,并使用 locals 参数允许使用本地函数。 例如,即使我们已经导入了sqrt()函数,以下内容也会限制它的使用。

from math import *
mycode='''a = sqrt(9)
print(a)'''
exec(mycode, {})

输出:

Traceback (most recent call last):
    exec(mycode, {})
  File "<string>", line 1, in >module>
NameError: name 'sqrt' is not defined

在上面的例子中,我们指定了一个空字典{}作为全局参数,这表示不允许全局或导入模块的函数,因此在 exec() 函数中调用 sqrt() 函数会抛出错误。 在全局字典中包含 sqrt() 函数以允许在exec()函数中,如下所示。

from math import *
mycode='''a = sqrt(9)
print(a)'''
exec(mycode, {'sqrt': sqrt})

输出:

3.0

您可以在exec()函数中添加内置或自定义函数以允许。例如,下面定义了指向sqrt()函数的sqroot()函数。 因此,您可以使用sqroot()函数代替sqrt()函数。

from math import *
mycode='''a = sqroot(9)
print(a)'''
exec(mycode, {'sqroot': sqrt})

输出:

3.0

还可以通过将值 None 传递给全局字典中的__builtins__来限制内置函数的使用。下面在调用内置函数 print() 时引发错误。

mycode='print("Hello World")'
exec(mycode, {'__builtins__': None})

输出:

Traceback (most recent call last):
    exec(mycode, {'__builtins__': None})
  File "<string>", line 1, in >module>
TypeError: 'NoneType' object is not subscriptable

locals 参数用于指定 exec() 方法中允许的局部函数或变量。请考虑以下示例。

def myfunc1():
	print('myfunc1')
def myfunc2():
	print('myfunc2')
globlsparam = {'__builtins__' : None}
localsparam = {'myfunc1': myfunc1}
exec('myfunc1', globlsparam, localsParameter) # valid
exec('myfunc2', globlsparam, localsparam) # throws error

输出:

myfunc1

Traceback (most recent call last):
exec('myfunc2', globlsparam, localsparam)
    File "<string>", line 10, in >module>
NameError: name 'myfunc2' is not defined

在上面的示例中,locals参数包含一个本地函数myfunc1()因此exec()函数可以调用myfunc1()但不能调用myfunc2()函数。 因此,我们可以使用全局和局部参数来限制全局和局部函数的使用。