使用Python timeit模块时偶发ImportError:无法从__main__导入N
解决timeit模块偶发ImportError: cannot import name 'N'的问题
问题原因
timeit在执行测试时会创建独立的执行上下文,原代码中通过from __main__ import computeArea, N导入变量的方式偶发报错,本质是主模块中N的赋值操作与timeit的导入动作存在时序竞争——部分场景下,timeit的setup语句执行时,主模块的N还未完成赋值,导致找不到该变量。
解决方案
以下几种方法可以彻底规避这个问题:
方法1:使用globals参数传递上下文
直接将主模块的全局命名空间传给Timer,timeit会直接访问其中的变量和函数,无需手动导入,从根源上避免时序问题:
N = number t = timeit.Timer( "computeArea(N, 4)", globals=globals() ) computeTime = t.timeit(1) print(computeTime)
或者用lambda表达式更直观:
N = number t = timeit.Timer( lambda: computeArea(N, 4), globals=globals() ) computeTime = t.timeit(1) print(computeTime)
方法2:绑定变量到函数调用
借助functools.partial把N预先绑定到computeArea的参数中,让timeit直接调用绑定后的函数,无需在测试语句中引用全局变量:
from functools import partial N = number bound_compute = partial(computeArea, N, 4) t = timeit.Timer(bound_compute) computeTime = t.timeit(1) print(computeTime)
方法3:在setup语句中定义变量
如果N的值可以提前确定,直接在timeit的setup语句中定义N,不用从主模块导入:
t = timeit.Timer( "computeArea(N, 4)", "from __main__ import computeArea; N = {}".format(number) ) computeTime = t.timeit(1) print(computeTime)
内容的提问来源于stack exchange,提问作者KarimIkramul
相关产品推荐
相关产品推荐

