Python 3.12中exec()与本地作用域赋值的循环局部变量缓存差异
Python 3.12中exec()与标准循环的性能差异及字节码优化疑问
我在研究Python 3.12的循环性能和局部变量查找(LOAD_FAST vs LOAD_DEREF)相关字节码优化时,发现本地函数作用域内动态执行代码与标准循环存在显著性能差异:两者均执行更新局部变量的密集循环,但使用exec()在同一本地上下文运行内部逻辑的场景,在Python 3.12.2中运行速度比标准循环慢3至4倍。
测试场景与代码
场景A:标准局部循环
场景B:exec()动态执行循环逻辑
测试代码如下:
import timeit # Setup A: Standard local loop def test_standard(): x = 0 for _ in range(10_000_000): x += 1 return x # Setup B: Executing loop logic dynamically def test_dynamic(): x = 0 local_vars = {'x': x} # Running the exact same loop structure inside exec exec(""" for _ in range(10_000_000): x += 1 """, globals(), local_vars) return local_vars['x'] print("Standard:", timeit.timeit(test_standard, number=1)) print("Dynamic (exec):", timeit.timeit(test_dynamic, number=1))
字节码分析
通过dis.dis查看底层实现:
- 对于
test_standard,Python使用LOAD_FAST和STORE_FAST操作码完成循环优化,因为x被严格映射到本地命名空间数组:
6 22 LOAD_FAST 0 (x) 24 LOAD_CONST 2 (1) 26 BINARY_OP 0 (+) 30 STORE_FAST 0 (x)
- 但
exec()内部生成的代码对象,即便传入了专用的local_vars字典,仍默认使用LOAD_NAME和STORE_NAME操作码。
疑问
- 既然Python 3.11+引入了自适应专用解释器,为何在检测到类型/字典结构未变化时,不对
exec()代码块内的LOAD_NAME进行本地化快速路径优化? - 是否存在严格的架构原因,导致
exec()代码对象从根本上无法使用LOAD_FAST优化机制,即使提供了明确的独立本地字典?
内容的提问来源于stack exchange,提问作者ttboy
相关产品推荐
相关产品推荐

