IPython中的单元格魔法
IPython拥有一些被称为"魔法"(magic)的命令,这些命令独立于Python语法,且用户可扩展出新的命令。"魔法"的设计初衷在于可以在IPython中交互式地执行一些命令(比如执行某些系统命令),所以它遵循了命令行的一些惯例,比如:使用空格来分隔参数,'-'来表示选项等。
"魔法"有两种:
- 行魔法(line magic): 以"%"为前缀,且整个命令(包括参数)不能跨行。
- 单元格魔法(cell magic): 以"%%"为前缀,而且整个单元格都被认为是一个命令。注意,单元格魔法必须从单元格的第一行开始,而且一般而言,一个单元格内仅能有一个单元格魔法。某些单元格魔法因为其特殊的操作机制,使得它们可以被叠加,但这种情况罕见,遇见时单独了解即可。
%lsmagic 会打印出当前所有可用的魔法,包括行魔法和单元格魔法:
In [1]:
%lsmagic
Out[1]:
Available line magics: %alias %alias_magic %autocall %automagic %autosave %bookmark %cat %cd %clear %colors %config %connect_info %cp %debug %dhist %dirs %doctest_mode %ed %edit %env %gui %hist %history %killbgscripts %ldir %less %lf %lk %ll %load %load_ext %loadpy %logoff %logon %logstart %logstate %logstop %ls %lsmagic %lx %macro %magic %man %matplotlib %mkdir %more %mv %notebook %page %pastebin %pdb %pdef %pdoc %pfile %pinfo %pinfo2 %popd %pprint %precision %profile %prun %psearch %psource %pushd %pwd %pycat %pylab %qtconsole %quickref %recall %rehashx %reload_ext %rep %rerun %reset %reset_selective %rm %rmdir %run %save %sc %set_env %store %sx %system %tb %time %timeit %unalias %unload_ext %who %who_ls %whos %xdel %xmode Available cell magics: %%! %%HTML %%SVG %%bash %%capture %%debug %%file %%html %%javascript %%js %%latex %%perl %%prun %%pypy %%python %%python2 %%python3 %%ruby %%script %%sh %%svg %%sx %%system %%time %%timeit %%writefile Automagic is ON, % prefix IS NOT needed for line magics.
In [6]:
%ls?
引入matplotlib和numpy,并使用%matplotlib inline
命令,可让我们方便地使用数值及绘图功能。
In [7]:
%matplotlib inline import numpy as np import matplotlib.pyplot as plt
一些简单的单元格魔法
为代码执行计时; 'timeit
'这个魔法既有行版本,也有单元格版本:
In [8]:
%timeit np.linalg.eigvals(np.random.rand(100, 100))
100 loops, best of 3: 4.74 ms per loop
In [9]:
%%timeit a = np.random.rand(100, 100) np.linalg.eigvals(a)
100 loops, best of 3: 4.15 ms per loop
%%capture
这个魔法可以用来捕获标准输出/错误:
In [10]:
%%capture capt import sys print 'Hello stdout' print >> sys.stderr, ' and stderr'
In [11]:
capt.stdout, capt.stderr
Out[11]:
('Hello stdout\n', ' and stderr\n')
In [12]:
capt.show()
Hello stdout
and stderr
%%writefile
魔法非常有用,它将单元格中的内容写入指定文件中:
In [13]:
%%writefile foo.py print 'Hello World'
Overwriting foo.py
In [14]:
%run foo
Hello World
在其他解释中执行代码的魔法
IPython有一个'%%script
'的单元格魔法,它可以让你在一个子进程中运行单元格内的各种其他解释器,如:bash,ruby,perl,zsh,R等。当然,前提是你的系统中必须有这些解释器。
告诉%%script
解释器的路径,然后在单元格中写下想要运行的代码即可。
In [15]:
%%script python import sys print 'hello from Python {}'.format(sys.version)
hello from Python 2.7.15 (default, Aug 22 2018, 16:36:18) [GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.2)]
IPython也为一些常用的解释器设置了一些快捷别名,如bash,ruby,perl等。
它们均等价于%%script <name>
In [16]:
%%ruby puts "Hello from Ruby #{RUBY_VERSION}"
Hello from Ruby 2.3.7
In [17]:
%%bash echo "hello from $BASH"
hello from /bin/bash
捕获输出
上面的子进程的输出可以被捕获并赋值给Python的变量:
In [18]:
%%script python --out output --err error import sys print 'from stdout' print >> sys.stderr, 'from stderr'
In [19]:
print error print output
from stderr from stdout
后台脚本
增加--bg
标志即可让子进程在后台执行而不阻塞我们的交互界面。
当我们采用这种后台执行的方式时,子进程的输出自动被忽略,除非我们像上面那样指定--out/err
来主动捕获。
In [20]:
%%script python --bg --out subprocess_out import time for i in range(0,10): time.sleep(0.5) print 'line #',i
Starting job # 0 in a separate thread.
In [21]:
subprocess_out
Out[21]:
<open file '<fdopen>', mode 'rb' at 0x114e76810>
In [22]:
for line in subprocess_out: print line
line # 0 line # 1 line # 2 line # 3 line # 4 line # 5 line # 6 line # 7 line # 8 line # 9