📅  最后修改于: 2020-09-20 04:01:55             🧑  作者: Mango
exec()
的语法:
exec(object, globals, locals)
exec()
具有三个参数:
稍后将在本文中讨论globals
和locals
globals
的使用。
exec()
不返回任何值,它返回None
。
program = 'a = 5\nb=10\nprint("Sum =", a+b)'
exec(program)
输出
Sum = 15
在这里, 字符串对象program
被传递给exec()
program
exec()
。在这种情况下,将省略globals
和locals
globals
。
program = input('Enter a program:')
exec(program)
输出
Enter a program: [print(item) for item in [1, 2, 3]]
1
2
3
如果要从允许多行代码的用户那里获取Python代码(使用'\n'
),则可以在使用exec()
之前使用compile()
方法。
了解有关Python的 compile()方法的更多信息。
考虑一种情况,您正在使用Unix系统(macOS,Linux等),并且已经导入了os
模块。 os模块提供了一种可移植的方式来使用操作系统功能,例如读取或写入文件。
如果允许用户使用exec(input())
输入值,则用户可以发出命令来更改文件,甚至可以使用命令os.system('rm -rf *')
删除所有文件。
如果您在代码中使用exec(input())
,则最好检查用户可以使用哪些变量和方法。您可以使用dir()方法查看可用的变量和方法。
from math import *
exec('print(dir())')
输出
['In', 'Out', '_', '__', '___', '__builtin__', '__builtins__', '__name__', '_dh', '_i', '_i1', '_i2', '_ih', '_ii', '_iii', '_oh', '_sh', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exit', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'get_ipython', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'quit', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
通常,不需要使用exec()
所有可用的方法和变量,甚至可能存在安全漏洞。您可以通过将可选的globals
和locals
参数(字典)传递给exec()
方法来限制这些变量和方法的使用。
如果两个参数都省略(如我们前面的示例),则预期由exec()
执行的代码在当前作用域中执行。您可以使用以下代码检查可用的变量和方法:
exec('print(dir())')
globals
和局部locals parameters
(字典)分别用于全局和局部变量。如果省略了locals
字典,则默认为globals
字典。这意味着, globals
将用于全局变量和局部变量。
注意:您可以分别使用globals()和locals()内置方法在Python检查当前的全局字典和局部字典。
from math import *
exec('print(dir())', {})
# This code will raise an exception
# exec('print(sqrt(9))', {})
如果将空字典作为globals
传递,则object
只能使用__builtins__
(exec()的第一个参数)。即使我们在上述程序中导入了math模块,尝试访问math模块提供的任何功能也会引发异常。
输出
['__builtins__']
from math import *
exec('print(dir())', {'sqrt': sqrt, 'pow': pow})
# object can have sqrt() module
exec('print(sqrt(9))', {'sqrt': sqrt, 'pow': pow})
在这里,由exec()执行的代码也可以具有sqrt()
和pow()
方法以及__builtins__
。
可以根据您的意愿更改方法的名称。
from math import *
exec('print(dir())', {'squareRoot': sqrt, 'pow': pow})
# object can have squareRoot() module
exec('print(squareRoot(9))', {'squareRoot': sqrt, 'pow': pow})
在上面的程序中, squareRoot()
计算平方根(类似功能,如sqrt()
)。但是,尝试使用sqrt()
将引发异常。
您可以通过为globals
词典中的'__builtins__'
赋予值None
来限制__builtins__
的使用。
exec(object, {'__builtins__': None})
您可以通过传递locals
字典来使所需的函数和变量可用。例如:
from math import *
globalsParameter = {'__builtins__' : None}
localsParameter = {'print': print, 'dir': dir}
exec('print(dir())', globalsParameter, localsParameter)
输出
['dir', 'print']
在这里, exec()
方法只能执行两个内置方法print()和dir()。
重要的是要注意, exec()
执行代码并且不返回任何值(返回None
)。因此,您不能在函数定义之外使用return和yield语句。