2012-04-28 97 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秒,但不會更多 - 除非一次調用該函數需要很長時間。