2012-04-28 131 views
37

IPython%timeit magic命令在测量运行某些Python代码所需的时间方面做得很好。现在,我想在Python脚本中使用类似的东西。我知道timeit模块,但是,它有几个缺点,例如,如何自适应选择运行次数?即默认代码如何从脚本运行IPython魔术(或计算Python脚本)

import timeit 
t=timeit.Timer("code(f)", "from __main__ import code,f") 
t.timeit() 

运行的代码亿次。 %timeit IPyhton magic命令自动执行。我认为,我可以使用类似的MATLAB代码 http://www.mathworks.com/matlabcentral/fileexchange/18798

自动完成所有的工作(也告知用户,如果功能的开销很大)。

如何从Python脚本调用%timeit魔术(或者有更好的时间解决方案)?

+7

如果您将其设置为IPython脚本(* .ipy),则所有IPython语法都将可用,并且您可以像平常一样执行'%timeit foo'。 – minrk 2012-04-28 17:50:20

+1

谢谢,这是一个很好的建议。但我在一个组织模式文件中使用它,我认为它只知道python :) – 2012-04-29 12:38:56

回答

44

这取决于你有哪个版本的IPython。如果你有1.x的:

from IPython import get_ipython 
ipython = get_ipython() 

如果你有一个旧版本:

import IPython.core.ipapi 
ipython = IPython.core.ipapi.get() 

import IPython.ipapi 
ipython = IPython.ipapi.get() 

一旦这样做了,运行一个神奇的命令是这样的:

ipython.magic("timeit abs(-42)") 

请注意,脚本必须通过ipython运行。

+2

看来,这不再受IPython的1.x的 – DaveP 2013-10-31 03:20:22

+1

这适用于IPython的1.x的工作原理: '从IPython的进口get_ipython' 'IPython中= get_ipython()' – suzanshakya 2014-02-06 09:14:04

+0

@suzanshakya get_ipython()似乎在一个实例返回None以前的工作。思想指向一个例子? – badgley 2014-02-27 23:52:52

5

IPython的和timeit模块两者,当与python -m timeit叫,用越来越值执行相同的循环,直到定时结果超过某一阈值,保证时间测量大多是自由的操作系统干扰。

您可以将IPython implementation of the %timeit magicPython timeit standard module进行比较,看看它们的效果大致相同。

所以,回答你的问题,你应该直到你找到了参数正确的值复制相同的循环。

+0

好吧,我可以复制timeit模块的“main”部分。不知道为什么它不包含在图书馆里。 – 2012-04-29 13:28:45

2

如果在IPython中以交互方式运行Python脚本,以下方法可行。例如,test.py

def f(): 
    # Algorithm 1 
    pass 

def g(): 
    # Algorithm 2 
    pass 

# which one is faster? 
mgc = get_ipython().magic 
mgc(u'%timeit f()') 
mgc(u'%timeit g()') 

然后在交互的IPython

%run -i test.py 

运行它吐出时机。 -i开关是必要的,以便变量在范围内。我还没有想出如何在不运行IPython实例的情况下执行此操作,即通过简单地从IPython中导入timeit并将其用作函数。但是,这种解决方案适用于我的目的,即自动化一些定时运行。

1

运行ipython magic函数的一种方法可能是使用嵌入ipython实例。
例如:(大部分代码被从ipython website借用)

from IPython.terminal.embed import InteractiveShellEmbed 

ipshell = InteractiveShellEmbed() 
ipshell.dummy_mode = True 
print('\nTrying to call IPython which is now "dummy":') 
ipshell.magic("%timeit abs(-42)"); 
ipshell() 
print('Nothing happened...') 

这可以通过使用Python解释
工作 PS:使用dummy_mode将防止调用交互式外壳。

+1

'from IPython import get_ipython; ipython = get_ipython()在v4.2.0上返回“AttributeError:'NoneType'”,但这似乎工作得很好。 – 16num 2016-08-28 15:59:05

1

按照timeit.py模块的documentation,当timeit在命令行模式下运行,

If -n is not given, a suitable number of loops is calculated by trying successive powers of 10 until the total time is at least 0.2 seconds.

这是IPython都做了什么。这就是为什么循环的数量始终是你可以通过嵌入的呼叫做在自己的代码相似的东西t.timeit()一个循环,使里面的10电源确保您不会等待太久:

import timeit 
t = timeit.Timer("code(f)", "from __main__ import code, f") 

max_time = 0.2 
N = 0 
curr_time = t.timeit(1) 

while curr_time < max_time: 
    N += 1 
    curr_time = t.timeit(10**N) 

mean_time = curr_time/float(10**N) 

这将确保分析时间至少为0.2秒,但不会更多 - 除非一次调用该函数需要很长时间。