交互式的開發環境 - ipython

本文介紹如何使用ipython進行快速的實驗和調試,閒話免談,直接經過demo進入主題。python

與操做系統交互

!cmd

在系統shell中執行cmdshell

In [35]: !ls
Gemfile        Gemfile.lock    README.md    Rakefile    bin        config        db        log        src

%cd directory

將系統目錄更改成directoryvim

In [36]: %cd -
/private/tmp

調試器

%debug

在執行完代碼,若是出現錯誤,當即執行%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()

%run -d xxx.py

一樣當即進入調試器。ide

性能分析

%timeit

用來測試各個部分或者函數的執行時間,它會自動屢次執行以產生一個很是精確的平均執行時間。函數

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 的性能要快兩倍以上。工具

%run -p

python的主要性能分析工具是cProfile模塊,它會記錄各個函數的耗費時間,在命令行中,能夠經過以下命令來進行性能分析:oop

python -m cProfile xxx.py

而在ipython中,會使用下面的命令來運行一個文件性能

%run -p -s cumulative xxx.py

%prun

若是想要運行一個函數或語句,請使用以下命令:測試

%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庫來分析。

%lprun

使用一個庫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,兩個問號來顯示該函數的源碼

%timeit

檢測python語句的執行時間

In [16]: %timeit  sum(i*i for i in xrange(1000))
10000 loops, best of 3: 68.6 µs per loop

%logstart

執行這個命令,開始記錄控制檯會話,這樣能夠將整個過程保存起來

相關文章
相關標籤/搜索