Python中的 exec()
exec()函数用于动态执行Python程序,可以是字符串或目标代码。如果它是一个字符串,则该字符串被解析为一组Python语句,然后执行,除非出现语法错误,如果它是一个目标代码,它就会被简单地执行。我们必须小心,即使在传递给 exec()函数的代码上下文中,也不能在函数定义之外使用 return 语句。它不返回任何值,因此返回None 。
句法:
exec(object[, globals[, locals]])
它可以接受三个参数:
- 对象:如前所述,这可以是字符串或对象代码
- globals:可以是字典,参数是可选的
- locals:可以是映射对象,也是可选的
现在让我们看看这个函数是如何工作的。在下面的代码中,我们使用了一个目标代码并使用 exec()函数执行它。我们刚刚获取了对象参数并省略了其他两个字段。
例子:
Python3
prog = 'print("The sum of 5 and 10 is", (5+10))'
exec(prog)
Python3
# The math class is used to include all the
# math functions
from math import *
exec("print(dir())")
Python3
# Here we have passed an empty dictionary
from math import *
exec("print(dir())", {})
Python3
# An exception will be raised
from math import *
exec("print(factorial(5))", {})
Python3
# factorial() will be executed
from math import *
exec("print(factorial(5))", {"factorial":factorial})
Python3
# factorial() renamed as fact
from math import *
exec('print(fact(5))', {'fact': factorial})
Python3
from math import *
exec("print(dir())", {"built" : __builtins__}, {"sum": sum, "iter": iter})
Python3
#__builtins__ has been restricted using None
from math import *
exec("print(dir())", {"__builtins__" : None}, {"sum": sum, "print": print, "dir": dir})
输出:
5和10的和是15
警告或限制
在使用 exec()函数中的任何方法之前,必须记住所有函数都支持什么 exec()。要查看这一点,我们可以使用 dir()函数。
例子:
Python3
# The math class is used to include all the
# math functions
from math import *
exec("print(dir())")
输出:
['__builtins__', '__cached__', '__doc__', '__file__',
'__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', 'sin',
'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
全局和局部参数
Python允许我们通过使用可能不需要的全局和局部参数来限制各种变量和方法的使用。这些局部和全局参数用于局部或全局变量,主要是字典。如果 local 缺失,则 global 参数将取代,这意味着 global 可以用于两个字段。让我们看看代码如何仅传递全局参数。
例子:
Python3
# Here we have passed an empty dictionary
from math import *
exec("print(dir())", {})
输出:
['__builtins__']
所以我们看到,在将空字典作为全局参数传递时,只显示 __builtins__ 而没有显示其他数学函数,如上例所示。这意味着 object 参数仅支持 __builtins__ 。这表明所有其他功能都受到对象的限制。为了证明这一点,让我们尝试使用数学函数,看看会发生什么。
例子:
Python3
# An exception will be raised
from math import *
exec("print(factorial(5))", {})
输出:
No Output
此示例应打印 120 作为输出,但它显示 No Output 并引发异常。虽然,我们已经导入了数学模块,但是由于我们通过传递全局参数设置的限制,factorial() 方法无法工作。
我们还可以允许执行许多功能中的少数几个。假设我们希望限制除 factorial()函数之外的所有其他数学模块。
例子:
Python3
# factorial() will be executed
from math import *
exec("print(factorial(5))", {"factorial":factorial})
输出:
120
我们还可以更改这些预定义方法的名称,并在执行期间为它们赋予用户定义的名称。我们可以将函数的名称从factorial()更改为fact() ,这是用户定义的。
例子:
Python3
# factorial() renamed as fact
from math import *
exec('print(fact(5))', {'fact': factorial})
输出:
120
现在让我们看看在传递全局和局部参数时我们还能做些什么。使用本地参数,我们可以根据需要实现功能。
例子:
Python3
from math import *
exec("print(dir())", {"built" : __builtins__}, {"sum": sum, "iter": iter})
输出:
['dir', 'print', 'sum']
通过这个,只有 sum 和 iter 方法以及所有内置方法可以在 exec()函数中执行。
我们还可以像这样限制 __builtins__ 的使用:
Python3
#__builtins__ has been restricted using None
from math import *
exec("print(dir())", {"__builtins__" : None}, {"sum": sum, "print": print, "dir": dir})
输出:
['dir', 'print', 'sum']