IPython Magic Functions

[ 2010-07-19 22:03:24 | 作者: yuhen ]
字号: | |
将 IPython 用熟了,可以轻松在试验、编码、测试间 "无缝折腾"。[lol]
$ ipython

Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
Type "copyright", "credits" or "license" for more information.

IPython 0.10 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object'. ?object also works, ?? prints more.

1. 帮助

?: 查看对象信息。
??: 获取更详细的信息,比如源代码。
%quickref: IPython 简易手册。
%magic: IPython Magic 详细手册。
%lsmagic: 所有可用的 Magic 函数。

"?" 和 "??" 是 IPython 中最常用的命令。
In [96]: test ?
Type:           function
Base Class:     <type 'function'>
String Form:    <function test at 0x190e1b8>
Namespace:      Interactive
File:           /home/yuhen/test/test.py
Definition:     test()
Docstring:
    <no docstring>

In [97]: test ??
Type:           function
Base Class:     <type 'function'>
String Form:    <function test at 0x190e1b8>
Namespace:      Interactive
File:           /home/yuhen/test/test.py
Definition:     test()
Source:
def test():
    pass

2. 系统

%alias: 显示或定义系统命令别名。
%unalias: 删除别名。
%sc: 执行系统命令,并将输出结果存储到变量。
%sx: 执行系统命令,并将输出结果分割存储成列表。

(1) 定义别名和 shell 下的意思差不多。
In [13]: %alias
Total number of aliases: 15
Out[13]:
[('cat', 'cat'),
 ('clear', 'clear'),
 ('less', 'less'),
 ('mkdir', 'mkdir'),
 ('rmdir', 'rmdir'),
 ('cp', 'cp -i'),
 ('lc', 'ls -F -o --color'),
 ('ldir', 'ls -F -o --color %l | grep /$'),
 ('lf', 'ls -F -o --color %l | grep ^-'),
 ('lk', 'ls -F -o --color %l | grep ^l'),
 ('ll', 'ls -lF'),
 ('ls', 'ls -F'),
 ('lx', 'ls -F -o --color %l | grep ^-..x'),
 ('mv', 'mv -i'),
 ('rm', 'rm -i')]

In [14]: %alias mydir ls -la %1

In [15]: mydir ~
ls: cannot access %1: No such file or directory
/home/yuhen:
total 88
drwxr-xr-x 12 yuhen yuhen 4096 2010-07-18 21:15 ./
drwxr-xr-x  3 root  root  4096 2010-06-13 09:44 ../
drwxr-xr-x  4 yuhen yuhen 4096 2010-07-11 11:07 backup/
-rw-------  1 yuhen yuhen 9228 2010-07-18 23:44 .bash_history
-rw-r--r--  1 yuhen yuhen  220 2010-06-13 09:44 .bash_logout
-rw-r--r--  1 yuhen yuhen 3103 2010-06-13 09:44 .bashrc

In [16]: %unalias mydir

还可以用 "%s" 来代替 "%1" 接收参数。

(2) 在执行系统命令时,通常以 "!" 开头(可省略)。还可以直接使用 Python 变量($var_name),如果需要引用系统环境变量,需要对 "$" 转义($$)。
In [20]: !df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/yuhen--server64-root
                       19G  1.8G   16G  10% /
none                  243M  216K  242M   1% /dev
none                  247M     0  247M   0% /dev/shm
none                  247M   48K  247M   1% /var/run
none                  247M     0  247M   0% /var/lock
none                  247M     0  247M   0% /lib/init/rw
/dev/sda1             228M   17M  199M   8% /boot

In [21]: path = "/var/www"

In [22]: !echo $path
/var/www

In [23]: !echo $$HOME
/home/yuhen

(3) %sc 捕捉输出结果到单个字符串变量, %sx 按 "\n" 切分成列表。
In [41]: %sc s = ls -l ~

In [42]: s
Out[42]: LSString (.p, .n, .l, .s available). Value:
total 20
drwxr-xr-x 4 yuhen yuhen 4096 2010-07-11 11:07 backup
drwxr-xr-x 3 yuhen yuhen 4096 2010-06-28 23:49 mongo
drwxr-xr-x 7 yuhen yuhen 4096 2010-06-27 09:30 projects
drwxr-xr-x 4 yuhen yuhen 4096 2010-06-16 19:43 redis
drwxr-xr-x 2 yuhen yuhen 4096 2010-07-18 23:03 test

In [43]: s = %sx ls -l ~

In [44]: s
Out[44]: SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):
0: total 20
1: drwxr-xr-x 4 yuhen yuhen 4096 2010-07-11 11:07 backup
2: drwxr-xr-x 3 yuhen yuhen 4096 2010-06-28 23:49 mongo
3: drwxr-xr-x 7 yuhen yuhen 4096 2010-06-27 09:30 projects
4: drwxr-xr-x 4 yuhen yuhen 4096 2010-06-16 19:43 redis
5: drwxr-xr-x 2 yuhen yuhen 4096 2010-07-18 23:03 test

可以用 "!!" 代替 %sx,但 "!!" 只能在命令开头,无法存储到变量中。
In [60]: s = !ls -l

In [61]: s
Out[61]: SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):
0: total 20
1: drwxr-xr-x 4 yuhen yuhen 4096 2010-07-11 11:07 backup
2: drwxr-xr-x 3 yuhen yuhen 4096 2010-06-28 23:49 mongo
3: drwxr-xr-x 7 yuhen yuhen 4096 2010-06-27 09:30 projects
4: drwxr-xr-x 4 yuhen yuhen 4096 2010-06-16 19:43 redis
5: drwxr-xr-x 2 yuhen yuhen 4096 2010-07-18 23:03 test

In [62]: s = !!ls -l
/bin/sh: !ls: not found

In [63]: !!ls -l
Out[63]: SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):
0: total 20
1: drwxr-xr-x 4 yuhen yuhen 4096 2010-07-11 11:07 backup
2: drwxr-xr-x 3 yuhen yuhen 4096 2010-06-28 23:49 mongo
3: drwxr-xr-x 7 yuhen yuhen 4096 2010-06-27 09:30 projects
4: drwxr-xr-x 4 yuhen yuhen 4096 2010-06-16 19:43 redis
5: drwxr-xr-x 2 yuhen yuhen 4096 2010-07-18 23:03 test

3. 目录

%pwd: 显示当前工作目录。
%cd: 切换工作目录。
%bookmark: 工作目录书签。
%dirs: 目录栈。
%pushd: 目录入栈
%popd: 目录出栈。

(1) cd 和 bookmark 配合起来用,非常方便。
In [146]: %pwd
Out[146]: '/home/yuhen/test'

In [148]: %bookmark test # 为当前目录定义书签

In [149]: %bookmark www /var/www # 为其他目录定义书签

In [155]: %bookmark -l # 显示书签列表
Current bookmarks:
pylib -> /usr/local/lib/python2.6/dist-packages/
test  -> /home/yuhen/test
www   -> /var/www

In [156]: %bookmark -d pylib # 删除书签

In [157]: %bookmark -l
Current bookmarks:
test -> /home/yuhen/test
www  -> /var/www

In [150]: cd -b www # 使用书签跳转,可省略 -b
(bookmark:www) -> /var/www
/var/www

In [151]: cd test
(bookmark:test) -> /home/yuhen/test
/home/yuhen/test

In [152]: cd -
/var/www

In [153]: cd
/home/yuhen

(2) 目录栈的使用和 shell 下没什么区别。
In [167]: %pwd
Out[167]: '/home/yuhen/test'

In [168]: %pushd /var/www
/var/www
Out[168]: ['~/test', '/var/www']

In [169]: %dirs
Out[169]: ['~/test', '/var/www']

In [170]: %popd
/home/yuhen/test
popd -> ~/test

4. 历史

%history: 显示历史。
%hist: %history 别名。
%dhist: 显示工作目录历史。
%clear: 清除历史数据。
%save: 保存输入命令到文件。

(1) 可以指定显示的行数,以及范围。
In [64]: %hist 5
60: s = _ip.magic("sc -l =ls -l")
61: s
62: s = _ip.magic("sc -l =!ls -l")
63: _ip.magic("sx ls -l")
64: _ip.magic("hist 5")

In [65]: %hist 32 35
32: s = _ip.magic("sx uname -a")
33: s
34: s = _ip.magic("sc -l =!uname -a")

(2) 可以清除输入(in)、输出(out) 以及目录(dhist) 等历史信息。
In [66]: %clear in
Flushing input history

In [67]: %clear out
Flushing output cache (23 entries)

In [68]: %clear dhist
Clearing directory history

(3) 可以将多个范围的输入数据保存到文件中。通常用于将交互环境中写的测试代码保存成源码文件。
In [38]: %save -r test.txt 33-34 36
File `test.txt.py` exists. Overwrite (y/[N])? y
The following commands were written to file `test.txt.py`:
ed test.py
ed a
%save test.txt 33-34 36

5. 执行

%bg: 使用独立线程在后台执行。
%rep: 获取上一次命令的输出,或提取某个历史命令。
%run: 执行源码文件,并将相关对象导入交互环境上下文。
%runlog: 执行记录文件中命令。这对于 "恢复现场" 是非常有帮助地。
%r: 重复执行上一次命令。

(1) %run 有几个重要的参数。

-n: 将 "__name__" 设置成非 "__main__",这样就可以仅导入成员,而不执行启动逻辑代码了。
-i: 将当前交互环境上下文作为源码文件默认上下文,如此源码文件就可以引用交互环境变量了。为源码测试准备环境非常方便。
-e: 忽略源码中的 "sys.exit()",否则会引发异常。
-t: 输出源码执行的时间信息。该参数还可以与 -N 配合,指定执行次数。
-d: 直接进入 pdb 调试状态,貌似有点问题。
-p: 启用 profiler 输出性能统计信息。
In [60]: abc = 1

In [62]: %pycat test.py

def test():
    print abc

def a():
    print "a"

if __name__ == "__main__":
    test()
    a()

In [63]: %run -i test.py
1
a

In [65]: %run -i -t -N5 test.py
1
a
1
a
1
a
1
a
1
a

IPython CPU timings (estimated):
Total runs performed: 5
  Times :      Total       Per run
  User  :       0.01 s,      0.002 s.
  System:        0.0 s,        0.0 s.

(2) %runlog 对于测试或者试验非常有帮助,可以轻松恢复现场。
In [1]: %logstart test.log
Activating auto-logging. Current session state plus future input saved.
Filename       : test.log
Mode           : backup
Output logging : False
Raw input log  : False
Timestamping   : False
State          : active

In [2]: a = 1

In [3]: b = 2

In [4]: a += b

In [5]: %logstop

In [6]: %pycat test.log
#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
#log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
#log# opts = Struct({'__allownew': True, 'logfile': 'test.log'})
#log# args = []
#log# It is safe to make manual edits below here.
#log#-----------------------------------------------------------------------
_ip.magic("logstart test.log")

a = 1
b = 2
a += b
_ip.magic("logstop ")

In [7]: %reset
Once deleted, variables cannot be recovered. Proceed (y/[n])?  y

In [8]: %who
Interactive namespace is empty.

In [9]: %runlog test.log
Loading log file <test.log> one line at a time...
Finished replaying log file <test.log>

In [10]: %who
a       b

In [11]: a
Out[11]: 3

In [12]: b
Out[12]: 2

(3) %rep 默认提取 "_" 变量的值。
In [50]: a = 1

In [51]: a
Out[51]: 1

In [52]: %rep

In [53]: 1 # 提取上一次的输出结果

In [54]: %rep 50

In [55]: a = 1 # 提取第 50 行命令

6. 编辑

%edit: 编辑源文件。
%ed: %edit 别名。

%edit 后面的参数可以是文件名,也可以是某个对象(比如某个函数名、类名等),还可以指定文件行号。
参数: "-n" 指定行号;"-x" 关闭时不执行源码(不执行也就意味着源码中的对象不会导入到交互上下文中,可执行 %run)。
In [32]: %pycat test.py

def test():
    pass

def a():
    print "a"

In [33]: ed test.py
Editing... done. Executing edited code...

In [34]: ed a
Editing... done. Executing edited code...

In [35]: ed -n 3 test.py
Editing... done. Executing edited code...

7. 记录

%logstart: 启动记录器。
%logon: 开始记录。
%logoff: 暂停记录。
%logstate: 查看记录状态。
%logstop: 关闭记录器。

(1) 首先需要用 %logstart 启动记录器,中间可以随时使用 %logon/%logoff 启动或暂停,末了别忘了关闭记录器,确保记录信息写到磁盘文件中。

参数: "-o" 记录输出,"-r" 记录正常的输入数据,"-t" 则是增加时间信息。
模式: 添加(append),备份(backup, 将已有文件改名 name~),单个文件(global),覆盖(over),循环(rotate, name.1~, name.2~)。
In [6]: %logstart -r -t test.log over
Activating auto-logging. Current session state plus future input saved.
Filename       : test.log
Mode           : over
Output logging : False
Raw input log  : True
Timestamping   : True
State          : active

In [7]: a = 1

In [8]: b = 2

In [9]: %logstate
Filename       : test.log
Mode           : over
Output logging : False
Raw input log  : True
Timestamping   : True
State          : active

In [10]: %logoff
Switching logging OFF

In [11]: %pycat test.log
#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
#log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
#log# opts = Struct({'__allownew': True, 'logfile': 'test.log'})
#log# args = []
#log# It is safe to make manual edits below here.
#log#-----------------------------------------------------------------------
%hist
ls
%hist
a = 1
%hist
%logstart -r -t test.log over

# Mon, 19 Jul 2010 21:23:07
a = 1
# Mon, 19 Jul 2010 21:23:09
b = 2
# Mon, 19 Jul 2010 21:23:15
%logstate
# Mon, 19 Jul 2010 21:23:21
%logoff

In [12]: %logon
Switching logging ON

In [13]: c = 3

In [14]: %logstop

In [15]: %pycat test.log
#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
#log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
#log# opts = Struct({'__allownew': True, 'logfile': 'test.log'})
#log# args = []
#log# It is safe to make manual edits below here.
#log#-----------------------------------------------------------------------
%hist
ls
%hist
a = 1
%hist
%logstart -r -t test.log over

# Mon, 19 Jul 2010 21:23:07
a = 1
# Mon, 19 Jul 2010 21:23:09
b = 2
# Mon, 19 Jul 2010 21:23:15
%logstate
# Mon, 19 Jul 2010 21:23:21
%logoff
# Mon, 19 Jul 2010 21:23:43
c = 3
# Mon, 19 Jul 2010 21:23:46
%logstop

(2) %logstart 启动后会连同该命令之前的历史记录一起保存,因此要想有个干净起点的话,最好调用 %clear 清理现场。%logoff 暂停记录,直到 %logon 调用前的记录都不会被保存。
In [1]: a = 1

In [2]: b = 2

In [3]: c = a + b

In [4]: %logstart test.log over
Activating auto-logging. Current session state plus future input saved.
Filename       : test.log
Mode           : over
Output logging : False
Raw input log  : False
Timestamping   : False
State          : active

In [5]: c
Out[5]: 3

In [6]: %logoff
Switching logging OFF

In [7]: d = c * 2

In [8]: %logon
Switching logging ON

In [9]: e = d / 2

In [10]: %logstop

In [11]: %pycat test.log
#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
#log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
#log# opts = Struct({'__allownew': True, 'logfile': 'test.log'})
#log# args = []
#log# It is safe to make manual edits below here.
#log#-----------------------------------------------------------------------
a = 1
b = 2
c = a + b
_ip.magic("logstart test.log over")

c
_ip.magic("logoff ")
e = d / 2
_ip.magic("logstop ")

8. 显示

%p: Python print 函数的缩写。
%pfile: 查看对象所在源码文件。
%pycat: 查看源代码文件。

注意 %pfile 跟的是对象或文件名,而 %pycat 后面只能是源码文件名(可省略 .py)。
In [55]: pfile a
def a():
    print "a"

In [56]: pycat test.py

def test():
    pass

def a():
    print "a"

9. 搜索

%psearch: 在当前上下文的命名空间中进行模糊搜索。

参数 -i 忽略大小写;-e 指定搜索的命名空间(builtin, user, user_global, internal, alias)。
In [63]: %psearch -i t*.S*
time.sleep
time.strftime
time.strptime
time.struct_time

In [65]: %psearch -e user_global t*.s*
time.sleep
time.strftime
time.strptime
time.struct_time

可以输入 CTRL + R 搜索历史命令。

10. 测试

%prun: 使用 profile 获取代码执行的性能统计。
%time: 获取代码执行时间。
%timeit: 通过多次循环,获得最佳的执行时间评测。

%timeit 参数 n 表示单个循环内的代码调用次数, r 表示循环次数。
for x in range(r):
    for y in range(n):
        <code segment>

这三个凑一起基本上就可以确定一段代码的性能了。
In [68]: def test(loop):
   ....:     for i in xrange(loop):
   ....:         time.sleep(0.001)
   ....:
   ....:

In [70]: %prun test(10)
         13 function calls in 0.019 CPU seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10    0.019    0.002    0.019    0.002 {time.sleep}
        1    0.000    0.000    0.019    0.019 <ipython console>:1(test)
        1    0.000    0.000    0.019    0.019 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

In [73]: %time test(10)
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.02 s

In [75]: %timeit -n 100 -r 5 test(1)
100 loops, best of 5: 1.93 ms per loop

11. 调试

%debug: 激活交互调试模式。
%pdb: 激活 pdb 调试模式,在引发异常时自动切入 pdb 调试命令行。

熟悉 pdb 是必须的,别老想着用 print,好歹 assert 也比那个强些。
In [10]: %pdb
Automatic pdb calling has been turned ON

In [11]: def test(i):
   ....:     print 10 / i
   ....:
   ....:

In [12]: test(0)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)

/home/yuhen/<ipython console> in <module>()

/home/yuhen/<ipython console> in test(i)

ZeroDivisionError: integer division or modulo by zero
> <ipython console>(2)test()

ipdb> p i
0

ipdb>

12. 环境

%env: 显示系统环境变量。
%who: 显示交互环境上下文可用变量(对象)。
%who_ls: 返回交互环境上下文变量列表。
%whos: 比 %who 多了类型和内容信息。

貌似 whos 比 dir() 更好用些。
In [5]: a = 1

In [6]: b = 2

In [7]: who
a       b

In [8]: who_ls
Out[8]: ['a', 'b']

In [9]: whos
Variable   Type    Data/Info
----------------------------
a          int     1
b          int     2

13. 配置

%Pprint: "pretty print" 开关。
%autocall: 所谓 autocall 就是无数输入函数括号。
%autoindent: 自动缩进开关。
%automagic: 打开时可省略 %magic 前的百分号。
%color_info: 彩色显示开关。
%colors: 彩色方案。
%doctest_mode: 在 IPython "[In]/[Out]" 和 Python ">>>" 提示符方式间切换。
%xmode: 更改异常报告模式。

(1) autocall 让我们不必输入 callobject 调用时的括号。
In [129]: def test(a, b):
   .....:     print a * b
   .....:
   .....:

In [130]: %autocall 0
Automatic calling is: OFF

In [131]: test 2, 3
------------------------------------------------------------
   File "<ipython console>", line 1
     test 2, 3
          ^
SyntaxError: invalid syntax

In [132]: %autocall 1
Automatic calling is: Smart

In [133]: test 2, 3
--------> test(2, 3)
6

不过就算 autocall off,我们也可以用 "/" 来偷懒。
In [138]: %autocall 0
Automatic calling is: OFF

In [139]: /test 2,3
--------> test(2,3)
6

(2) 如果你习惯了 Python 提示符,那么可以用 doctest_mode 切换。
In [126]: %doctest_mode
Exception reporting mode: Plain
Doctest mode is: ON

>>> print "abc"
abc

>>> %doctest_mode
Exception reporting mode: Context
Doctest mode is: OFF

In [129]:

(3) 更改异常报告模式。
In [118]: a = 10

In [119]: def test(i):
   .....:     print a / i
   .....:
   .....:

In [120]: xmode
Exception reporting mode: Verbose

In [121]: test(0)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)

/home/yuhen/test/<ipython console> in <module>()

/home/yuhen/test/<ipython console> in test(i=0)

ZeroDivisionError: integer division or modulo by zero

In [122]: xmode
Exception reporting mode: Plain

In [123]: test(0)
------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
  File "<ipython console>", line 2, in test
ZeroDivisionError: integer division or modulo by zero

In [124]: xmode
Exception reporting mode: Context

In [125]: test(0)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)

/home/yuhen/test/<ipython console> in <module>()

/home/yuhen/test/<ipython console> in test(i)

ZeroDivisionError: integer division or modulo by zero

14. 其他

%Exit: 退出 IPython,无提示。
%exit: 退出 IPython,有提示。
%Quit: 相当于 %Exit。
%quit: 相当于 %exit。
%reset: 重置 IPython,清理相关环境对象,但历史信息被保留。
[最后修改由 yuhen, 于 2010-07-20 00:48:12]
评论Feed 评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=1029

浏览模式: 显示全部 | 评论: 5 | 引用: 0 | 排序 | 浏览: 684
引用 yuhen
[ 2010-07-19 22:25:56 ]
[angry] 群里的童鞋看此贴不回者交总管咔嚓。
[最后修改由 yuhen, 于 2010-07-19 22:26:24]
引用 tttick
[ 2010-07-20 08:51:20 ]
老大V5
终于看到你的 试验、编码、测试、调试一体化了
V5V5V5V5V5V5V5
引用 yunchou
[ 2010-07-20 08:56:24 ]
上次只瞻仰了风范
这次终于可以学习了
引用 yuhen
[ 2010-07-20 12:07:52 ]
[sweat] 瞻仰?听着真别扭。
引用 Ling
[ 2010-07-21 04:03:58 ]
占座 等着学

发表评论
表情图标
[smile] [confused] [cool] [cry]
[eek] [angry] [wink] [sweat]
[lol] [stun] [razz] [redface]
[rolleyes] [sad] [yes] [no]
[heart] [star] [music] [idea]
UBB代码
转换链接
表情图标
悄悄话
用户名:   密码:  
验证码 * 请输入验证码