Python exec()
Python exec()函数提供了对动态代码执行的支持。
Python exec()
Python exec()函数签名为:
exec(object, globals, locals)
对象–它应该是字符串或者代码对象。
如果是字符串,则将其解析为python语句块,然后执行它。
全局变量–用于指定可由exec()函数执行的全局函数。
它必须是字典。
如果未定义__builtins__,则所有内置函数均可用于exec函数。
locals –用于指定可用的局部函数和变量。
它可以是任何映射对象。
但是,字典最好与全局变量相似。
Python exec()函数返回None。
因此,它不能与return和yield语句一起使用。
Python exec()与eval()
Python exec()和eval()函数非常相似。
它们的用法和对动态代码执行的支持也非常相似。
但是,exec()和eval()函数之间存在一个主要区别。
Python exec()函数不返回任何内容,而eval()函数计算表达式并将值返回给调用代码。
Python exec()示例
让我们看一个简单的python exec()函数示例。
x = 1 exec('print(x==1)') exec('print(x+2)')
输出:
True 3
Python exec()动态代码执行
让我们看另一个示例,用户将其中输入要由我们的程序执行的代码。
from math import * for l in range(1, 3): func = input("Enter Code Snippet to execute:\n") try: exec(func) except Exception as ex: print(ex) break print('Done')
示例输出:
Enter Code Snippet to execute: print(sqrt(16)) 4.0 Enter Code Snippet to execute: print(min(2,1)) 1 Done
请注意,我正在使用数学模块中的sqrt(),print()和min()是内置函数。
Python exec()安全风险
由于我们可以执行任何代码,因此存在与exec()函数相关的安全风险。
如果有人导入os模块并发出os.system('rm -rf /')
命令,该怎么办?这将使我们的系统崩溃,因为所有文件都将被删除。
这是全局和局部参数派上用场以限制访问的时候。
Python exec()全局变量和局部变量
在决定exec()应该可用的功能之前,最好使用dir()
函数获取可用功能和模块的列表。
from math import * def square_root(n): return sqrt(n) exec('print(dir())') # list of names in the current local scope
输出:
['__annotations__', '__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', 'remainder', 'sin', 'sinh', 'sqrt', 'square_root', 'tan', 'tanh', 'tau', 'trunc']
这有很多功能,包括内置模块,数学模块和我们定义的函数square_root。
让我们看看如果提供全局值作为空字典会发生什么情况。
exec('print(dir())',{})
输出:
['__builtins__']
因此,如果全局变量没有密钥,则可以使用内置函数。
让我们看看如何指定仅从内建模块访问某些功能的权限。
exec('print(min(1,2))',{"__builtins__":{"min": min, "print": print}}) #1
让我们看另一个示例,在该示例中我们将定义全局参数和局部参数值。
y=5 exec('print(y+1)',{"__builtins__": None}, {"y": y, "print": print}) # 6
让我们看一个最后的示例,在该示例中,我们将仅提供对一些数学模块功能的访问。
from math import * for l in range(1, 3): func = input("Enter Code Snippet with Math Function to execute.\nFor Examples; print(squareRoot(x)) and print(pow(x,y)):\n") try: exec(func, {"squareRoot": sqrt, "pow": pow}) except Exception as ex: print(ex) break print('Done')
示例输出:
Enter Code Snippet with Math Function to execute. For Examples; print(squareRoot(x)) and print(pow(x,y)): print(squareRoot(100)) 10.0 Enter Code Snippet with Math Function to execute. For Examples; print(squareRoot(x)) and print(pow(x,y)): print(max(2,4)) 4 Done
我们可以指定一个自定义名称以使用任何函数进行映射,例如已经定义了squareRoot来映射到sqrt函数。
请注意,内置函数是可用的,因为我没有明确排除它们。
因此,定义exec()的更好方法是:
exec(func, {"squareRoot": sqrt, "pow": pow, "__builtins__": None, "print": print})
示例输出为:
Enter Code Snippet with Math Function to execute. For Examples; print(squareRoot(x)) and print(pow(x,y)): print(squareRoot(100)) 10.0 Enter Code Snippet with Math Function to execute. For Examples; print(squareRoot(x)) and print(pow(x,y)): print(max(2,4)) 'NoneType' object is not subscriptable Done
现在出现错误,因为exec()函数无法访问max()函数。