为何使用if __name__ == '__main__'调用main会使运行时长增加38%?
问题:为何使用
if __name__ == "__main__"结构会使代码运行时长增加38%? 我在学习装饰器教程时修改了代码,代码如下:
from time import perf_counter def is_prime(num): if num <= 1: return False for i in range(2, int(num**0.5) + 1): if num % i == 0: return False return True def count_prime_numbers(upper_bound): count = 0 for num in range(upper_bound): if is_prime(num): count += 1 print(f"Number of primes: {count}") return count def benchmark(func): def wrapper(*args, **kwargs): start_time = perf_counter() value = func(*args, **kwargs) end_time = perf_counter() run_time = end_time - start_time print(f"Execution of {func.__name__} took {run_time:0.3f} seconds") return value return wrapper def main(): wrapper = benchmark(count_prime_numbers) value = wrapper(100000) if __name__ == "__main__": main()
当使用上述if __name__ == '__main__'结构调用main函数时,代码运行时长为0.132秒;但移除该结构直接执行对应逻辑时,运行时长仅为0.096秒。请问为何使用该结构会导致运行时长增加38%?
解答
这种差异主要由Python解释器的函数调用层级、优化策略以及字节码缓存时机共同导致:
- 多一层函数调用的栈开销:用
main函数包裹逻辑时,相当于多了一层函数调用——解释器需要为main函数创建栈帧、处理局部变量(比如wrapper),执行完成后还要销毁栈帧,这会带来额外的运行开销。而直接在顶层执行代码时,没有这一层额外的函数调用栈操作。 - 闭包与函数引用的优化差异:
benchmark返回的wrapper是嵌套闭包函数。当在main内部创建并调用wrapper时,解释器对闭包函数的调用处理比顶层函数调用更复杂,无法触发某些针对全局函数调用的轻量优化;而顶层执行时,wrapper作为全局变量,解释器可以直接定位函数对象,调用效率更高。 - 字节码缓存时机不同:顶层代码中的
wrapper在模块加载阶段就完成了创建和字节码编译,缓存更充分;而main函数里的wrapper是在运行时动态生成的,首次创建时需要额外的编译时间,拉高了整体运行时长。
如果要缩小这种差异,可以尝试:
- 多次运行取平均值,消除首次运行的编译缓存差异
- 将
wrapper的创建移到顶层,只在main里调用它,比如:
这种方式既保留wrapper = benchmark(count_prime_numbers) def main(): value = wrapper(100000) if __name__ == "__main__": main()if __name__ == "__main__"的结构,又避免了在main内部动态创建闭包的开销。
内容的提问来源于stack exchange,提问作者Joseph Coleridge
相关产品推荐
相关产品推荐

