Python 基础教程

Python 流程控制

Python 函数

Python 数据类型

Python 文件操作

Python 对象和类

Python 日期和时间

Python 高级知识

Python 参考手册

Python exec() 使用方法及示例

Python 内置函数

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

exec()的语法;

exec(object, globals, locals)

exec()参数

exec()采用三个参数:

  • object -字符串或代码对象

  • globals (可选)-字典

  • locals(可选)-映射对象。字典是Python中常用的标准映射类型。

稍后将在本文中讨论全局变量(globals) 和 (locals)本地变量的使用。

exec()返回值

exec()不返回任何值,它返回None。

示例1:exec()如何工作?

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

运行该程序时,输出为:

Sum = 15

在这里,字符串对象程序被传递给执行该程序的exec()。在本示例中省略了全局变量(globals) 和 (locals)局部变量。

示例2:允许用户提供输入

program = input('输入程序:')
exec(program)

运行该程序时,输出为:

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

如果要从允许多行代码的用户处获取Python代码(使用'\n'),则可以在使用exec()之前使用compile()方法。

了解有关Python中的compile()方法更多信息。

使用exec()时要小心

考虑一种情况,您正在使用Unix系统(macOS,Linux等),并且已导入os模块。os模块提供了使用操作系统功能的便携式方法,例如:读取或写入文件。

如果允许用户使用来输入值exec(input()),则用户可以发出命令来更改文件,甚至可以使用command删除所有文件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()中使用可用的方法和变量

通常,不需要使用exec()中所有可用的方法和变量,甚至可能有安全漏洞。您可以通过将可选的globalslocals参数(字典)传递给exec()方法来限制这些变量和方法的使用。

1.全局(globals) 和 (locals)局部参数均被省略

如果两个参数都省略(如我们前面的示例),则exec()预期要执行的代码将在当前范围内执行。您可以使用以下代码检查可用的变量和方法:

exec('print(dir())')

传递全局参数;省略locals参数

(globals) 和 (locals)参数(字典),分别用于全局和局部变量。如果省略了locals字典,则默认为globals字典。这意味着,全局变量(globals)将用于全局变量和局部变量。

注意:您可以分别使用globals()locals()内置方法在Python中检查当前的全局字典和局部字典。

将空字典作为全局参数传递

from math import *
exec('print(dir())', {})

# 此代码将引发异常
# exec('print(sqrt(9))', {})

如果将空字典作为globals传递,则仅__builtins__可供object(exec()的第一个参数)使用。即使我们在上述程序中导入了math模块,尝试访问math模块提供的任何函数也会引发异常。

运行该程序时,输出为:

['__builtins__']

使某些方法可用

from math import *
exec('print(dir())', {'sqrt': sqrt, 'pow': pow})

# 对象可以有sqrt()模块
exec('print(sqrt(9))', {'sqrt': sqrt, 'pow': pow})

在这里,由exec()执行的代码也可以具有sqrt()和pow()方法以及__builtins__。

可以根据您的意愿更改方法的名称。

from math import *
exec('print(dir())', {'squareRoot': sqrt, 'pow': pow})

# 对象可以具有squareRoot()模块
exec('print(squareRoot(9))', {'squareRoot': sqrt, 'pow': pow})

在上述程序中,squareRoot()计算平方根(类似的功能,如sqrt())。但是,尝试使用sqrt()将引发异常。

限制使用内置

您可以通过在globals字典中为__builtins__赋值None,来限制__builtins__的使用。

exec(object, {'__builtins__': None})

3.通过全局和本地字典

您可以通过传递本地(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语句。

Python 内置函数