使用IPython
IPython简介
有时候仅需要通过几行 Python 代码来执行一些简单的功能,或测试某个库的基本使用方式。此时专门再编写一个脚本运行不免有些麻烦。好在 Python 提供了一个命令行的交互式控制台,可以立即执行输入的每一条语句并暂时保存变量。例如;
交互式控制台的特点在于其的交互功能,它可以直接查看变量的值,这样就避免了在简单的脚本中大量使用 print()
。
然而,Python 自带的交互式控制台功能过于薄弱。它没有语法高亮,没有自动补全,并且对缩进的处理也不够自然。如果代码较多,那么不但编写容易出错,而且难以阅读。
因此许多项目都尝试增强原有交互式控制台的功能。bpython 就是其中之一,bpython 在原有控制台的功能的基础上,提供了代码高亮、自动补全、括号匹配、缩进处理等功能,大大优化了交互体验。以下是 bpython 的简单交互效果:
bpython 可以通过命令行快速安装,但它目前只支持 Linux 系统。
IPython 则是一个更加强大的改进版交互式控制台,它不但支持代码高亮、自动补全等功能,还实现了跨平台以及更加丰富的扩展功能。以下是 IPython 的效果演示:
从截图中可以看到,IPython 还具有以下功能:
IPython 使用一个个单元格(cell)来对输入及输出编号,相比原先 Python 的提示符更加清晰。
单元格及其编号也为获取历史记录提供了一些便利。在 Python 的交互式控制台中都有一个特殊变量单下划线 _
,它保存着上次访问的对象信息,而 IPython 则具有更多这样的特殊变量,例如:
_i4
用于获取 In[4] 单元的代码
- 两个下划线
__
用于获取上上次访问的对象信息:
这样的特殊变量还有很多。并且从返回的结果来看,IPython 还提供了更加美观的打印效果:列表、字典等会换行对齐展示,更易于阅读。IPython 也对其它常见的输出做了一定优化,使其更便于展示。
在 2 号单元格内,执行了以下命令:
这不是标准的 Python 语法,而是 IPython 的扩展语法,在某个函数或类后面添加一个问号可以显示其文档字符串。IPython 提供了更丰富的扩展语法,使得某些基础的功能可以通过简单的命令实现。再如,IPython 将一些简单的命令行功能整合进了扩展语法中:
IPython 通过 pip
就可以安装。接下来介绍 IPython 更多类似这样的扩展语法。
IPython的高级功能
提示与帮助
前文介绍了 IPython 可以在函数或类后面加上一个问号获取它的文档帮助。实际上,对于任意的对象都可以用此方法查看它的基本信息:
除此之外,还可以通过两个问号 ??
来获取函数的源代码:
当然,如果源代码不是使用 Python 编写的,那么就只能获取到一些基本信息了。
单个问号还可以配合通配符检查命名空间中所有匹配的成员:
IPython 还提供了强大的自动补全功能。在访问模块或类的成员时,可以通过 TAB 键获取其包含的成员提示:
shell交互
IPython 还可以直接与命令行交互,使用 !
符号作为前缀可以执行命令行命令:
注意,在 Windows 系统上默认调用的是 DOS 而不是 PowerShell 命令,即使 IPython 是通过 PowerShell 启动的。
该命令甚至还能作为一个值赋给变量:
这个结果有点类似列表,但它实际上是 IPython 提供的一种增强版列表,它提供了更多操作方法,例如使用函数或正则字符串筛选合适元素:
也可以实现相反方向的交互,通过 {var}
将 Python 变量传入 shell :
魔法命令
IPython 中的一个更强大的功能是魔法命令(magic command),魔法命令可以用一种简洁的形式解决各种常见问题。
魔法命令以 %
符号作为前缀,如果要让魔法命令作用于整个单元,那么以两个 %%
作为前缀。魔法命令是一个很复杂的系统,接下来只介绍各种常用的魔法命令。
%run file
是一个很常用的魔法命令,它可以执行某一个 Python 脚本,在执行完后由 IPython 接管环境。这在 Debug 的时候很好用,当抛出异常时可以自动切换到 IPython 环境,此时可以使用 IPython 检查异常位置一些变量的值,或者查看异常的回溯栈等,在非图形界面下也可以很好地调试。
%timeit
也是一个很常用的魔法命令,用于分析一条或一块语句执行时长,这在科学计算或分析性能瓶颈的时候非常有用:
直接从 Python 命令行控制台中复制的代码会带上提示符,如果要使用它还必须去除提示符。使用 %paste
命令可以从剪贴板中获取并执行代码,同时消除提示符的影响:
配合特殊变量 In
可以获取去除提示符的实际执行的代码:
这里对魔法命令暂时就介绍这么多。可以通过 %magic
打开魔法命令的帮助文档,所有魔法命令可以通过 %lsmagic
获取,通过使用 ?
符号就可以了解每个魔法命令的使用。
使用Jupyter notebook
简介与安装
IPython 的功能非常丰富,甚至超越了原生 Python 的功能。然而 IPython 毕竟只是个命令行的控制台,进一步提升的空间被限制了。
基于此,IPython 发展出了一种更强大的编辑器模式:Jupyter Notebook 。Notebook 具有可视化的编辑界面,并使用文件来编辑与保存单元格的内容。
以下是 Jupyter Notebook 的使用截图:
Jupyter 在保留 IPython 特点的同时,功能与交互性都更加强大。
Jupyter 的安装十分简单,只需要通过 pip
安装即可:
注:目前主流的 Jupyter 安装和管理都是通过 Anaconda 完成的,这里使用命令行仅仅是为了简化使用与配置。关于 Anaconda 的使用网络上已经有较多文章,这里不再重复。
然后在命令行中就可以启动 Notebook :
这会在浏览器中打开一个新的页面,稍等片刻后便会进入 Notebook 的初始界面:
认识Notebook
Jupyter Notebook 也是基于文件执行的,其文件后缀为 .ipynb
,它实质上是一个 Json 文件,只有使用 Jupyter 等支持的编辑器打开才能正常被渲染。在 Jupyter 提供的浏览器页面中,可以像别的编辑器一样新建、修改和保存这种文件,还可以将其导出为 Python 代码、Markdown 文本、PDF 文档等。
进入 Jupyter 后,它提供了 3 个选项卡:
- Files 页用于管理工作路径下的文件
- Running 页显示当前正在运行的终端和 Notebooks
- Clusters 页用于处理计算群集
新建或打开一个 Notebook 文件后,即可像 IPython 一样在各个单元格内编写、执行代码:
但与 IPython 不同的是,Notebook 单元格的代码可以修改后重新执行,这会使得虽然上面某个单元格的代码修改了,但是下面单元格的输出结果还没更新,并且原始的数据也会被覆盖。注意单元格左侧 In 中的编号才表示真正的执行顺序。
Jupyter 提供的菜单中有各种功能,例如新建或保存文件、合并或移动单元格、控制显示内容等,它们使用较为简单,这里就不展开介绍了。
Notebook 中的单元格除了可以编写代码,还可以使用其余类型的单元格,例如通过 Markdown 单元格编写简单文档并嵌入 LaTeX 公式,或者使用 Raw 单元格显示纯文本。一些 Notebook 的扩展还允许它编写 bash 脚本、执行 R 语言甚至 SQL 命令等。
Notebook 的单元格在编写代码时,具有以下两种模式:
- 编辑模式:此时单元格外围的边框颜色为绿色,可以直接在该单元格中输入代码或文本
- 命令模式:此时单元格外围的边框颜色为蓝色,键盘操作将作为命令执行
点击单元格代码外区域或使用快捷键 Esc 即可进入命令模式,此时可以使用以下常用的命令对单元格做调整:
命令 | 功能 | 命令 | 功能 |
---|---|---|---|
L | 在单元格中显示或取消显示代码行号 | X | 剪切选中的单元格 |
M | 将该单元格变为 Markdown 类型 | C | 复制选中的单元格 |
Y | 将该单元格变为 Code 类型 | V | 将单元格粘贴到当前单元格下方 |
A | 在当前单元格上方插入一个 Code 单元格 | Shift+↑ 或 Shift+↓ | 向上或向下连续选择多个单元格 |
返回编辑模式可以点击代码区域或使用快捷键 Enter 。运行代码可以使用如下快捷键,它们在任意模式下都可以直接使用:
- Ctrl+Enter :运行选中单元格
- Shift+Enter :运行选中的单元格,并选中下一个单元格
- Alt+Enter :运行选中的单元格,并在下方插入一个新的单元格
配置Jupyter
Jupyter 的某些配置可以修改以满足使用要求。
在启动时可以通过命令行参数临时修改配置。例如 Jupyter 运行的默认端口号是 8888 ,可以通过如下参数修改端口号:
如果需要永久更改某个配置,那么就需要使用配置文件。初次使用需要通过如下命令生成配置文件:
然后可以根据提示信息找到配置文件的位置。该文件是一个纯 Python 文件,使用变量保存所有的配置信息,并且默认情况下配置都被注释了。
如果要启用某项配置只需要取消注释即可,这些配置的说明都在注释中写的很明白了。例如,假设要更改 Jupyter 打开后的根目录,那么可以修改以下配置:
管理内核
Notebook 在浏览器前端编写代码后,由内核(kernel)负责执行并返回结果。内核保存着单元格中的所有变量,因此一个 Notebook 所有的代码都在一个内核中执行。
在编辑界面中,可以在 kernel 菜单中终止或重启内核。但需要注意的是:内核一旦中断,所有的变量都会丢失,只有重新执行才可以访问这些变量。
在使用 Python 的过程中,免不了要管理各种虚拟环境,此时就需要管理 Jupyter 的各种内核。内核管理需要借助 ipykernel
第三方库实现,不过它应该在安装 Jupyter 时已经作为一个依赖被一并安装了。
使用以下命令即可查看当前 Jupyter 具有的全部内核:
每个内核都是一个目录,它主要包含以下文件:
logo-32x32.png
logo-64x64.png
logo-svg.svg
通过在 kernels 目录中创建多个类似这样的目录并修改 kernel.json 文件的内容,即可创建多个使用不同解释器的内核。kernel.json 文件中的内容为:
这里主要修改 "argv"[0]
决定的解释器路径和 "display_name"
决定的内核名,启动 Jupyter 后就能在 Kernel 菜单中更换内核并使用不同的虚拟环境了:
高级交互效果
借助浏览器的前端技术,Jupyter 可以使用在命令行甚至一般的编辑器中无法实现的交互效果。
在之前介绍 Jupyter 时就展示了在单元格内显示,借助 IPython.display
模块的各种显示类,可以在浏览器中显示各种格式的文本、数学公式乃至多媒体文件等:
还可以使用控件(widget)实现更强大的交互效果。控件的实现由第三方库 ipywidgets
提供,它应该在安装 Jupyter 时就被一并安装了,如果没有的话也可以使用 pip
安装它。
先来看一个最简单的示例,在输出中显示一个滑块:
交互最主要的就是处理各种事件,这可以通过向 .observe()
方法提供回调函数实现。每次发生交互时,事件的相关信息将以字典的形式由回调函数处理:
由于许多动作都会导致事件的发生,因此这里通过 names
参数限制处理的事件,即只有选定的值发生变化时才处理该事件。滑块在滑动过程中会不断触发事件,在复杂操作时可能引起卡顿。如果想让滑块在最终释放时才执行动作,那么可以在初始化时将 continuous_update
参数设置为 False
。
按钮之类的特殊控件没有那么多交互逻辑,可以使用其它方法简化处理,例如:
给多个控件建立联系也是很常见的做法,这点可以通过 link()
函数实现。例如,以下在一个滑块和进度条之间建立联系,使滑块的位置被同步反映到进度条上:
如果要建立单向联系,可以使用 dlink()
。这种联系的后台交互由内核实现,因此内核断开后就无法继续使用。如果要使用纯前端方法实现的联系,可以使用 jslink()
和 jsdlink()
。
一种更为强大的交互效果由 interact()
函数实现。该函数可以根据初始值自动选择合适的控件展示,以下简单展示了几个示例:
ipywidgets 的内容非常复杂,它不仅包含了大量常用的输入框、按钮、框架盒系列的控件,还允许对控件的样式做详细的定制,这里就不展开说明了。要了解更多有关它的内容,可以参考官方文档。
JupyterLab:更强大的Notebook IDE
Jupyter 作为 Notebook 的开发环境,只提供了基本的界面及一些简单的单元格编辑与处理功能。JupyterLab 则是一个更高级的浏览器 Notebook 开发环境,它提供了更加丰富的功能,其使用截图如下:
用过 VS Code 等编辑器的话应该会对该界面比较熟悉,JupyterLab 提供了更实用的文件管理、预览、分屏、状态显示等功能,并且还可以通过安装扩展进一步丰富其功能。
JupyterLab 可以通过 pip
快速安装:
然后就可以在命令行中运行:
Jupyter 及 Notebook 的发展远没有结束,除了以上介绍的技术外,Jupyter Hub 可以用于多人协同开发,而各个常用 Python IDE(如 Pycharm 和 VS Code )也推出了内置的 Notebook 开发环境,使 Notebook 可以使用它们提供的代码补全、语法检查、调试、环境管理等更多功能。