关于Python:Python – 克服timeit中的导入

Python - Overcome import in timeit

我最近注意到关于timeit python模块的以下内容:

我的机器上的线条:

1
2
3
from timeit import Timer
t = Timer(stmt='a = 2**3**4')
print("This took {:.3f}s to execute.".format(t.timeit()))

将产生:

This took 0.017s to execute.

另一方面写一个文件test.py:

1
2
3
#!/usr/bin/env python3

a = 2**3**4

并致电:

1
2
3
from timeit import Timer
t = Timer(stmt='import test')
print("This took {:.3f}s to execute.".format(t.timeit()))

将产生:

This took 0.126s to execute.

我想知道如何在不改变文件本身的情况下测试test.py的执行时间。 我如何处理导入文件(因此失去时间)。


当您写作时,您的测量存在一个问题:您没有测量您认为测量的是什么:

1
t = Timer(stmt= 'a = 2**3**4')

你正在测量绑定时间!看:

1
2
3
4
>>> Timer(stmt='a = 10**5**4').timeit(100000)
    0.0064544077574026915
>>> Timer(stmt='a = 2**3**4').timeit(100000)
    0.006511381058487586

时间几乎相同,但计算10**5**42**3**4稍长。编译代码时,2**3**4只计算一次,这称为"常量折叠",Python在编译源代码时执行的一些优化。

比较这两个结果:

1
2
3
4
>>> Timer(stmt= 'a = 2**3**4').timeit(100000)
    0.00628656749199763
>>> Timer(stmt= 'a = x**y**z', setup='(x,y,z)=(2,3,4)').timeit(100000)
    0.18055968312580717

但这种加速不是免费提供的。有两点:

  • 编译时间增加
  • .pyc文件大小增加(因为此值存储在.pyc文件中)
  • 假设我有两个文件:

    1
    2
    3
    4
    5
    6
    #foo1.py
    a = 10**7**7

    #foo2.py
    x,y,z =(10,7,7)
    a = x**y**z

    如果我用python -m py_compile foo1.py foo2.py编译它们,我机器上.pyc文件的大小将为:

  • foo1.cpython-36.pyc - 364  882个字节
  • foo2.cpython-36.pyc - 150个字节

  • 你最接近的是使用compileexec如果你打算作为.pyc文件运行,不要在你的计时中包含compile语句。

    1
    2
    3
    4
    5
    6
    7
    # time as if executing:">python test.pyc" from terminal
    #   (importing test.py will typically automatically generate the .pyc file automatically)
    t = Timer(stmt='exec(code_object)',
              setup='code_object = compile(open("test.py").read(),"test.py","exec")')

    # time as if executing:">python test.py" from terminal
    t = Timer(stmt='exec(compile(open("test.py").read(),"test.py","exec"))')

    这应该让您接近从终端调用脚本的实际时间。这不会消除开销,因为调用脚本的开销是真实的,并且将在现实世界中观察到。

    如果您使用的是基于Linux的系统,您也可以从终端呼叫>time test.py