IPython生产力特性

Posted by iXay on January 28, 2016

“你的Python开发环境是什么?”

“IPython外加一个文本编辑器。”

这个经典的问答来自著名的python数据处理包pandas的作者Wes McKinney. IPython作为python的交互式计算和开发环境,”生产力”是他最大的特点。下面简单介绍一些IPython的生产力特性。

1. Tab键自动补全

可补全内容包括:变量名、函数名、成员变量函数、目录文件。

2. 内省

在变量的前面或后面加上一个问号(?)就可以将有关该对象的一些通用信息显示出来。

In [1]: b = [1, 2, 3]

In [2]: b?
Type:        list
String form: [1, 2, 3]
Length:      3
Docstring:
list() -> new empty list
list(iterable) -> new list initialized from iterable's items

可以用?来显示docstring, 使用??还将显示对应的源代码。
另外?还有一个用法,即搜索IPython命名空间,类似于标准UNIX或Windows命令行中的那种用法。一些字符再配以通配符(*)即可显示出所有与该通配符表达式相匹配的名称。例如,我们可以列出NumPy顶级命名空间中含有”load”的所有函数:

In [9]: np.*load*?
np.load
np.loads
np.loadtxt
np.pkgload

3. %run命令

%run运行的python脚本在一个空的命名空间中运行,运行结束后所定义的全部变量可以在当前的IPython shell中访问。

4. 执行剪贴板中的代码

有的代码直接粘贴进来会出问题,于是%cpaste就派上用场了。
%cpaste在粘贴完成后输入一行’–‘或者按ctrl-d即可

5. 魔术命令

IPython有一些特殊命令,有的为常见任务提供便利,有的则使你能够轻松控制IPython系统的行为。魔术命令是以百分号%为前缀的命令。
例如,用%timeit检测Python语句的执行时间

In [10]: a = np.random.randn(100, 100)

In [11]: %timeit np.dot(a, a)
The slowest run took 70.39 times longer than the fastest. This could mean that an intermediate result is being cached
10000 loops, best of 3: 82.2 us per loop

魔术命令可以用?查看其用法。
魔术命令默认是可以不带百分号%使用的,只要没有定义与其同名的变量即可。这个技术叫做automagic,可以通过%automagic打开或关闭。
附上常用的Python魔术命令。

命令 说明
%quickref 显示IPython的快速参考
%magic 显示所有魔术命令的详细文档
%debug 从最新的异常跟踪的底部进入交互式调试器
%hist 打印命令的输入(可选输出)历史
%pdb 在异常发生后自动进入调试器
%paste 执行剪贴板中的Python代码
%cpaste 打开一个特殊提示符以便手工粘贴待执行的Python代码
%reset 删除interactive命名空间中的全部变量/名称
%page OBJECT 通过分页器打印输出OBJECT
%run script.py 在IPython中执行一个Python脚本文件
%prun statement 通过cProfile执行statement,并打印分析器的输出结果
%time statement 报告statement的执行时间
%timeit statement 多次执行statement以计算系综平均执行时间。对那些执行时 间非常小的代码很有用
%who、%who_ls、%whos 显示interactive命名空间中定义的变量,信息级别/冗余度可变
%xdel variable 删除variable,并尝试清除其在IPython中的对象上的一切引用

6. 输入和输出变量

输入文本被保存在名为_iX的变量中,其中X是输入行的行号。每个输入变量都有一个对应的输出变量_X_iX_X对应到IPython的InOut变量中。 由于输入变量是字符串,因此可以用Python的exec关键字重新执行

In [30]: exec _i27

有几个魔术命令可用于控制输入和输出历史。%hist用于打印全部或部分输入历史,可以选择是否带行号。%reset用于清空interactive命名空间,并可选择是否清空输入和输出缓存。%xdel用于从IPython系统中移除特定对象的一切引用。详细信息请参考相应魔术命令的文档。

7. 记录输入和输出

IPython能够记录整个控制台会话,包括输入和输出。执行%logstart即可开始记录日志

In [29]: %logstart
Activating auto-logging. Current session state plus future input saved.
Filename       : ipython_log.py
Mode           : rotate
Output logging : False
Raw input log  : False
Timestamping   : False
State          : active

相关魔术命令还有:%logoff, %logon, %logstate, %logstop

8. 与操作系统交互

IPython跟操作系统结合紧密,可以直接在IPython中实现命令行活动。 与系统相关的IPython命令如下:

!cmd 在系统shell中执行cmd
output=!cmd args 执行cmd,并将结果放在output中
%bookmark 使用IPython的目录书签系统
%cd directory 更改工作目录
%pwd 返回系统当前工作目录
%env 以字典形式返回系统环境变量

9. 目录书签系统

IPython的目录书签系统能够保存常用目录的别名以便实现快速跳转。书签能够持久化保存。

如:

%bookmark pys 'C:/User/xxx/PyWorkSpace' 定义好书签之后,就可以在执行魔术命令%cd时使用这些书签了:

cd pys 列出所有书签:

%bookmark -l 书签名与目录冲突

%bookmark -b pys 强制使用书签目录

10. 交互式调试器

IPython增强了pdb,如Tab键自动完成、语法高亮、为异常信息添加上下文参考等。

代码调试的最佳时机就是错误发生的时候,在发生异常之后马上输入 %debug 命令将会调用调试器,并直接跳转到引发异常的那个帧。

在pdb中,可以查看各个帧中的一切对象和数据。默认是从最低级开始的。输入u(p)d(own)可以在栈的各级别之间切换。

使用 %pdb on 命令可以开启自动调试功能, 即当程序异常时直接开始进行调试。%pdb off命令可关闭自动调试。如果不加参数,只输入%pdb命令则在两种模式之间切换。

如果你想设置断点或对函数进行单步调试。 可以使用带有 -d 选项的%run命令,这将会在执行脚本文件中的代码之前打开调试器。然后,如果你想套设置断点,那么使用 b(reak) x 命令,其中x为行号。前进一行使用 n(ext) 命令,进入函数体使用 s(tep into) 然后使用 c(ontinue) 命令即可直行至断点处。要查看变量可以使用 !x ,其中x为变量名。

run -d ipython_bug.py
b 12
c

想要精通这个交互式调试器,必须经过大量的实践才行。如果你习惯了使用某款IDE刚开始使用这种终端型调试器可能会觉得有点麻烦,但慢慢就习惯了。虽然大部分IDE都拥有优秀的GUI调试器,但是在IPython中调试程序却往往会带来更高的生产率。

pdb主要命令如下:

h(elp) 显示命令列表
help command 显示命令的说明文档
c(continue) 回复程序的执行
q(uit) 退出调试器
b(reak) number 在指定行设置断点
s(tep) 单步进入(step into)函数
n(next) 执行当前行(step over),并进入下一行
u(p)/d(own) 在函数调用栈中向上或向下移动
a(rgs) 显示当前函数的参数
debug statement 在新的调试器中调用语句statement
l(ist) statement 显示当前行,以及当前栈级别上的上下文参考代码
w(here) 打印当前位置的完整栈跟踪

11. 调试器的其他使用场景

除了上面提到的,还有另外的调试方法。可以使用set_trace这个特别的函数。下面两个函数或许会对你很有用(你也可以像我一向直接将其添加到IPython配置中):

def set_trace():
from IPython.core.debugger import Pdb
Pdb(color_sheme='Linux').set_trace(sys._getframe().f_back)

def debug(f, *args, **kwargs):
from IPython.core.debugger import Pdb
pdb = Pdb(color_scheme='Linux')
return pdb.runcall(f, *args, **kwargs)

第一个函这set_trace很简单,你可以将它放在代码中任何希望停下来查看一番的地方:

def calling_things():
set_trace()  #自定义的调试函数
works_fine()
throws_an_exception()

第二个函数(debug),使你能够直接在任意函数上使用调试器。

假设我们有如下函数:

def f(x, y, z=1):
tmp = x + y
return tmp / z

现在想对其进行单步调试,按如下方式即可:

debug(f, 1, 2, z=3)

12. 基本性能分析: %prun%run -p

代码性能分析与代码执行时间分析的区别在于,它关注的是耗费时间的位置。

python使用cProfile模块进行性能分析,它会记录各函数所耗费的时间。

使用方法如下:

python -m cProfile cprof_example.py

执行之后会发现输出结果是按函数名排序的,这我们很难发现哪里才是最花时间的地方,一次通常会再加一个 -s 指定排序规则:

python -m cProfile -s cumulative cprof_example.py

除此自外,cProfile还能以编程的方式分析任意代码块的性能。IPython为此提供了一个方便的接口。即 %prun 和带 -p 命令的%run

%prun 格式跟cProfle相同,但它分析的是部分语句而不是整个文件。

%prun -l 7 -s cumulative run_experiment()

利用 %run -p 也能达到上面的系统命令的效果去无需退出IPython:

%run -p -s cumulative cprof_example.py

13. 逐行分析函数性能

有时从%prun得到的信息要么不足以说明函数的执行时间,要么复杂到难以理解。这是我们可以使用一个叫做line_profiler的小型库(可以通过PyPI或其他包管理工具获取)。其中有一个新的魔术函数%lprun,它可以对一个或多个函数进行逐行性能分析。

14. IPython HTML Notebook

IPython Notebook目前已成为一种非常棒的交互式计算工具,同时还是科研和教学的一种理想媒介。它有一种基于JSON的文档格式.ipynb,一种流行的演示手段就是使用IPython Notebook再将.ipynb文件发布到网上以供所有人查阅。

IPython Notebook是一个运行于命令行上的轻量级服务器进程。

由于我们是在一个Web浏览器上使用Notebook的,因此该服务器进程可以运行于任何其他地方。甚至可以连接到那些运行在云服务上的Notebook。

15. 重新加载模块依赖项

  • reload 重加载模块
  • dreload 递归重加载模块

16. 个性化和配置

IPython shell在外观(如颜色、提示符、行间距)和行为方面的大部分内容都是可以配置的,如:

  • 颜色方案
  • 输入输出提示符
  • 去掉Out提示符后的空行
  • 执行任意的Python语句,你可以定制你希望每次启动IPython都发生的事
  • 启动IPython扩展
  • 自定义魔术命令或系统别名
  • 所有的配置项都在一个叫做 ipython_config.py 的文件中,可以在%HOME%/.ipython/目录中找到。