本文介紹如何使用ipython進行快速的實驗和調試,閒話免談,直接經過demo進入主題。python
在系統shell中執行cmdshell
In [35]: !ls Gemfile Gemfile.lock README.md Rakefile bin config db log src
將系統目錄更改成directoryvim
In [36]: %cd - /private/tmp
在執行完代碼,若是出現錯誤,當即執行%debug命令後將會進入調試器。在接觸%debug以前,筆者都是使用的是pdb.set_trace來調試程序,這樣的硬編碼很是之不方便。dom
In [45]: !touch a.py In [46]: !vim a.py In [47]: !cat a.py def divide(): assert(1 == 0) divide() In [56]: %run a.py --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) /private/tmp/a.py in <module>() 2 assert(1 == 0) 3 ----> 4 divide() /private/tmp/a.py in divide() 1 def divide(): ----> 2 assert(1 == 0) 3 4 divide() AssertionError: In [57]: %debug > /private/tmp/a.py(2)divide() 1 def divide(): ----> 2 assert(1 == 0) 3 4 divide()
一樣當即進入調試器。ide
用來測試各個部分或者函數的執行時間,它會自動屢次執行以產生一個很是精確的平均執行時間。函數
In [12]: strings = ['foo', 'foobar', 'baz','qux', '123 ffd'] * 100000
In [13]: %timeit method1 = [x for x in strings if x.startswith('foo')] 10 loops, best of 3: 93.4 ms per loop
In [14]: %timeit method2 = [x for x in strings if x[:3] == 'foo'] 10 loops, best of 3: 36.4 ms per loop
method2 比 method1 的性能要快兩倍以上。工具
python的主要性能分析工具是cProfile模塊,它會記錄各個函數的耗費時間,在命令行中,能夠經過以下命令來進行性能分析:oop
python -m cProfile xxx.py
而在ipython中,會使用下面的命令來運行一個文件性能
%run -p -s cumulative xxx.py
若是想要運行一個函數或語句,請使用以下命令:測試
%prun -l 7 -s cumulative run()
待測函數:
In [17]: from numpy.random import randn In [18]: x = randn(3000, 3000) In [19]: y = randn(3000, 3000) In [20]: def add_and_sum(x,y): ...: added = x + y ...: summed = added.sum(axis=1) ...: return summed ...:
使用prun的結果以下:
In [21]: %prun add_and_sum(x, y) 6 function calls in 0.340 seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 0.310 0.310 0.335 0.335 <ipython-input-16-fbadffca33af>:1(add_and_sum) 1 0.025 0.025 0.025 0.025 {method 'reduce' of 'numpy.ufunc' objects} 1 0.005 0.005 0.340 0.340 <string>:1(<module>) 1 0.000 0.000 0.025 0.025 {method 'sum' of 'numpy.ndarray' objects} 1 0.000 0.000 0.025 0.025 _methods.py:31(_sum) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
上面的結果不是很好理解,筆者更喜歡用line_profiler庫來分析。
使用一個庫line_profiler,這個庫的輸出結果簡單易理解。
這個庫不是內建的,須要手動安裝,安裝命令:
pip install line_profiler
而後在ipython中手動load lprun:
In [2]: %load_ext line_profiler In [3]: %lprun Timer unit: 1e-06 s
待測函數:
In [17]: from numpy.random import randn In [18]: x = randn(3000, 3000) In [19]: y = randn(3000, 3000) In [20]: def add_and_sum(x,y): ...: added = x + y ...: summed = added.sum(axis=1) ...: return summed ...: In [21]: def call_function(): ...: x = randn(1000, 1000) ...: y = randn(1000, 1000) ...: return add_and_sum(x, y)
使用lprun後的結果以下:
In [23]: %lprun -f add_and_sum -f call_function call_function() Timer unit: 1e-06 s Total time: 0.004438 s File: <ipython-input-16-fbadffca33af> Function: add_and_sum at line 1 Line # Hits Time Per Hit % Time Line Contents ============================================================== 1 def add_and_sum(x,y): 2 1 3929 3929.0 88.5 added = x + y 3 1 508 508.0 11.4 summed = added.sum(axis=1) 4 1 1 1.0 0.0 return summed Total time: 0.062512 s File: <ipython-input-17-b03b81a6d2ba> Function: call_function at line 1 Line # Hits Time Per Hit % Time Line Contents ============================================================== 1 def call_function(): 2 1 29193 29193.0 46.7 x = randn(1000, 1000) 3 1 28449 28449.0 45.5 y = randn(1000, 1000) 4 1 4870 4870.0 7.8 return add_and_sum(x, y)
一般,會使用%prun(cProfile)作「宏觀」性能分析,而用%lprun(line_profiler)作「微觀」性能分析。使用line_profiler必需要指定待測的函數,是由於這個庫要跟蹤每一行代碼的執行時間。
在一個變量的前面或後面加上問號?,能夠顯示該變量的基本信息
In [23]: a=1 In [24]: a? Type: int String form: 1 Docstring: int(x=0) -> int or long int(x, base=10) -> int or long >>> int('0b100', base=0) 4
若是這個變量是函數的話,一個問號?來顯示docstring,兩個問號來顯示該函數的源碼
檢測python語句的執行時間
In [16]: %timeit sum(i*i for i in xrange(1000)) 10000 loops, best of 3: 68.6 µs per loop
執行這個命令,開始記錄控制檯會話,這樣能夠將整個過程保存起來