Python exec 函数
上次修改时间:2025 年 4 月 11 日
这份全面的指南探讨了 Python 的 exec
函数,该函数执行动态创建的代码。我们将涵盖语法、作用域处理、安全注意事项以及动态执行的实际示例。
基本定义
exec
函数从字符串或代码对象动态执行 Python 代码。它可以修改当前命名空间并执行复杂的代码块。
主要特点:将源代码作为字符串,在给定的命名空间中执行,返回 None,并且可以根据上下文影响局部/全局变量。
基本字符串执行
这是一个简单的用法示例,展示了 exec
如何从字符串执行 Python 代码并修改当前命名空间。
code = """ x = 10 y = 20 print(x + y) """ exec(code) # Outputs: 30 # Variables are now in the namespace print(x) # 10 print(y) # 20
此示例显示 exec
执行一个多行代码字符串。该代码创建变量并执行影响当前作用域的操作。
执行后,变量 x 和 y 在当前命名空间中可用,这证明了 exec 修改环境的能力。
使用命名空间控制作用域
exec
可以在特定的命名空间中执行代码,以控制变量的访问和修改。此示例展示了如何使用自定义字典。
global_ns = {} local_ns = {} code = """ a = 1 b = 2 print(a + b) """ exec(code, global_ns, local_ns) print("Global:", global_ns) # Contains builtins print("Local:", local_ns) # Contains a and b
这将在隔离的命名空间中执行代码。全局命名空间包含内置函数,而局部命名空间包含已执行代码的变量。
此技术对于沙箱环境或者当您需要控制哪些变量被执行的代码修改时非常有用。
动态函数创建
exec
可以在运行时动态创建函数。此示例展示了如何从字符串生成和使用函数。
func_code = """ def dynamic_multiply(x, y): return x * y """ exec(func_code) result = dynamic_multiply(5, 7) print(result) # 35
代码字符串定义了一个函数,exec
使该函数在当前命名空间中可用。然后,我们可以像调用任何常规函数一样调用它。
这演示了如何将 exec
用于元编程和运行时代码生成场景。
安全注意事项
此示例演示了使用 exec
处理未经处理的输入的危险以及如何降低风险。
# Dangerous example (never do this with user input!) user_input = "__import__('os').system('rm -rf /')" try: exec(user_input) except: print("Prevented dangerous operation") # Safer alternative with restricted globals safe_globals = {'__builtins__': None} exec("print('Safe code')", safe_globals)
第一部分展示了如果提供不受信任的输入,exec
如何执行危险代码。第二部分演示了使用受限全局变量的安全执行方法。
使用 exec
时,始终验证和清理输入,或者完全避免使用用户提供的代码。
模板处理
exec
可以通过将变量注入到代码字符串中来用于简单的模板处理。
template = """ for i in range({count}): print(f"Item {i+1}/{count}") """ context = {'count': 3} exec(template.format(**context))
此示例展示了一个基本的模板系统,我们在执行之前将变量注入到代码模板中。格式化的字符串变为有效的 Python 代码。
虽然不建议用于复杂的模板(请改用专用库),但它演示了 exec
在代码生成方面的灵活性。
最佳实践
- 避免用户输入: 如果没有适当的沙箱环境,切勿执行不受信任的代码
- 使用命名空间: 使用自定义全局变量/局部变量控制变量访问
- 考虑替代方案: 通常 eval() 或 ast.literal_eval() 更安全
- 彻底记录: 在代码中清楚地记录任何 exec 用法
- 限制范围: 尽可能限制对内置函数的访问
资料来源
作者
列出所有 Python 教程。