重要

本文档涵盖 IPython 6.0 及更高版本。从 6.0 版本开始,IPython 不再支持与低于 Python 3.3 的 Python 版本(包括所有版本的 Python 2.7)兼容。

如果您正在寻找与 Python 2.7 兼容的 IPython 版本,请使用 IPython 5.x LTS 版本并参考其文档(LTS 是长期支持版本)。

IPython Sphinx 指令

注意

IPython Sphinx 指令处于“测试版”阶段,目前正在积极开发中。欢迎对代码或文档进行改进!

ipython 指令是一个有状态的 shell,可用于重构文本文件中。

它了解标准 ipython 提示符,并提取输入和输出行。这些提示符将从 1 开始重新编号。输入将馈送到嵌入式 ipython 解释器,并且该解释器的输出也将插入。例如,以下代码块

.. ipython::

   In [136]: x = 2

   In [137]: x**3
   Out[137]: 8

将呈现为

In [1]: x = 2

In [2]: x**3
Out[2]: 8

注意

本教程应与该文档的 Sphinx 源码并排阅读,因为否则您将只看到呈现的输出,而看不到生成它的代码。除了上面的示例外,我们通常不会在本文档中显示生成呈现输出的字面 ReST。

指令和选项

IPython 指令采用此处详述的许多选项。

.. ipython::

创建 IPython 指令。

:doctest:

对 rst 中的 IPython 代码块运行 doctest。

:python:

用于指示相关代码块没有 IPython 提示符。

:okexcept:

允许代码块引发异常。

:okwarning:

允许代码块发出警告。

:suppress:

忽略所有警告或预期错误。

:verbatim:

一个允许任何文本作为有效 IPython 代码进行语法高亮的空操作。

:savefig: OUTFILE [IMAGE_OPTIONS]

将 matplotlib 的输出保存到 outfile

请务必注意,所有这些选项均可用于整个指令块,或者它们可以装饰单个代码行,如 伪装饰器 中所述。

在 IPython 指令块中持久化 Python 会话

存储先前会话的状态,并捕获标准错误。在文档构建时,将插入 ipython 的输出和标准错误,并将重新对提示符进行编号。因此,下面的提示符应在呈现的文档中重新编号,并从上面块离开的位置继续。

In [3]: z = x*3   # x is recalled from previous block

In [4]: z
Out[4]: 6

In [5]: print(z)
6

In [6]: q = z[)   # this is a syntax error -- we trap ipy exceptions
------------------------------------------------------------
   File "<ipython console>", line 1
     q = z[)   # this is a syntax error -- we trap ipy exceptions
           ^
SyntaxError: invalid syntax

向 IPython 指令添加文档测试

嵌入式解释器支持一些有限的标记。例如,你可以在 ipython 会话中添加注释,这些注释将逐字报告。有一些方便的“伪装饰器”,可让你对输出进行 doctest。输入将馈送到嵌入式 ipython 会话中,而 ipython 会话的输出将插入到你的文档中。如果你的文档和 ipython 会话中的输出在 doctest 断言上不匹配,则会发生错误。

In [7]: x = 'hello world'

# this will raise an error if the ipython output is different
In [8]: x.upper()
Out[8]: 'HELLO WORLD'

# some readline features cannot be supported, so we allow
# "verbatim" blocks, which are dumped in verbatim except prompts
# are continuously numbered
In [9]: x.st<TAB>
x.startswith  x.strip

有关 @doctest 装饰器的更多信息,请参阅伪装饰器部分本页末尾的内容。

多行输入

支持多行输入。

In [10]: url = 'http://ichart.finance.yahoo.com/table.csv?s=CROX\
   ....: &d=9&e=22&f=2009&g=d&a=1&br=8&c=2006&ignore=.csv'
   ....: 

In [11]: print(url.split('&'))
['http://ichart.finance.yahoo.com/table.csv?s=CROX', 'd=9', 'e=22',

测试指令输出

IPython Sphinx 指令可以测试你随代码提供的输出。为此,请使用上面列出的一个选项装饰指令块中的内容。

如果找到 IPython doctest 装饰器,则在构建文档时它将执行以下步骤

1. 在当前 Python 内核上运行 IPython 指令块中的输入行(请记住,该会话在 IPython 指令块中持续存在);

2. 将此输出与你放入 IPython 指令块中的输出文本进行比较(即 Out[NN] 之后的文本);

  1. 如果存在差异,则指令将引发错误,并且你的文档构建将失败。

你还可以对多行输出进行 doctest。在 ipython 指令中使用随机数等非确定性输入时要小心,因为你的输入是通过实时解释器运行的,所以如果你对随机输出进行 doctest,则会收到错误。这里我们“播种”随机数生成器以获得确定性输出,并且我们抑制种子行,以便它不会显示在呈现的输出中

In [12]: import numpy.random

In [13]: numpy.random.rand(10,2)
Out[13]: 
array([[0.64524308, 0.59943846],
       [0.47102322, 0.8715456 ],
       [0.29370834, 0.74776844],
       [0.99539577, 0.1313423 ],
       [0.16250302, 0.21103583],
       [0.81626524, 0.1312433 ],
       [0.67338089, 0.72302393],
       [0.7566368 , 0.07033696],
       [0.22591016, 0.77731835],
       [0.0072729 , 0.34273127]])

有关 @suppress 和 @doctest 装饰器的更多信息,请参阅伪装饰器部分本文件的末尾内容。

多行输入和输出的另一个演示

In [14]: print(x)
jdh

In [15]: for i in range(10):
   ....:     print(i)
   ....: 
   ....: 
0
1
2
3
4
5
6
7
8
9

大多数“伪装饰器”可以用作 ipython 模式的选项。例如,要设置 matplotlib pylab 但禁止输出,您可以执行以下操作。使用 matplotlib use 指令时,它应在导入 pylab 之前出现。这不会在呈现的文档中显示,但命令将在嵌入式解释器中执行,并且后续行号将递增以反映输入

.. ipython::
   :suppress:

   In [144]: from matplotlib.pylab import *

   In [145]: ion()

同样,您可以设置 :doctest::verbatim: 以将这些设置应用于整个块。例如,

In [16]: cd mpl/examples/
/home/jdhunter/mpl/examples

In [17]: pwd
Out[17]: '/home/jdhunter/mpl/examples'

In [18]: cd mpl/examples/<TAB>
mpl/examples/animation/        mpl/examples/misc/
mpl/examples/api/              mpl/examples/mplot3d/
mpl/examples/axes_grid/        mpl/examples/pylab_examples/
mpl/examples/event_handling/   mpl/examples/widgets

In [19]: cd mpl/examples/widgets/
/home/msierig/mpl/examples/widgets

In [20]: !wc *
    2    12    77 README.txt
   40    97   884 buttons.py
   26    90   712 check_buttons.py
   19    52   416 cursor.py
  180   404  4882 menu.py
   16    45   337 multicursor.py
   36   106   916 radio_buttons.py
   48   226  2082 rectangle_selector.py
   43   118  1063 slider_demo.py
   40   124  1088 span_selector.py
  450  1274 12457 total

您可以创建一个或多个 pyplot 图形,并使用 @savefig 装饰器插入它们。

有关 @savefig 装饰器的更多信息,请参阅本页末尾的“伪装饰器”部分。

In [21]: plot([1,2,3]);

# use a semicolon to suppress the output
In [22]: hist(np.random.randn(10000), 100);
_images/plot_simple.png _images/hist_simple.png

在后续会话中,我们可以使用一些文本更新当前图形,然后重新保存

In [23]: ylabel('number')
Out[23]: Text(38.347222222222214, 0.5, 'number')

In [24]: title('normal distribution')
Out[24]: Text(0.5, 1.0, 'normal distribution')

In [25]: grid(True)
_images/hist_with_text.png

您还可以在源代码中包含函数定义。

In [26]: def square(x):
   ....:     """
   ....:     An overcomplicated square function as an example.
   ....:     """
   ....:     if x < 0:
   ....:         x = abs(x)
   ....:     y = x * x
   ....:     return y
   ....: 

然后从后续部分调用它。

In [27]: square(3)
Out[27]: 9

In [28]: square(-2)
Out[28]: 4

编写纯 Python 代码

可选参数 python 支持纯 python 代码。在此纯 python 语法中,您不包括 python 解释器的输出。以下标记

.. ipython:: python

   foo = 'bar'
   print(foo)
   foo = 2
   foo**2

呈现为

In [29]: foo = 'bar'

In [30]: print(foo)
bar

In [31]: foo = 2

In [32]: foo**2
Out[32]: 4

我们甚至可以使用 savefig 装饰器从 python 绘制图形,以及使用分号禁止输出

In [33]: plot([1,2,3]);
_images/plot_simple_python.png

有关 @savefig 装饰器的更多信息,请参阅本页末尾的“伪装饰器”部分。

同样,插入 std err

In [34]: foo = 'bar'

In [35]: foo[)
  Cell In[35], line 1
    foo[)
        ^
SyntaxError: closing parenthesis ')' does not match opening parenthesis '['

处理注释

处理注释并保留状态

# comments are handled
In [36]: print(foo)
bar

如果您看不到下一个代码块,则选项有效。

跨行拆分 Python 语句

处理多行输入。

In [37]: line = 'Multi\
   ....:         line &\
   ....:         support &\
   ....:         works'
   ....: 

In [38]: print(line.split('&'))
['Multi        line ', '        support ', '        works']

函数定义被正确解析

In [39]: def square(x):
   ....:     """
   ....:     An overcomplicated square function as an example.
   ....:     """
   ....:     if x < 0:
   ....:         x = abs(x)
   ....:     y = x * x
   ....:     return y
   ....: 

并且跨会话持久存在

In [40]: print(square(3))
9

In [41]: print(square(-2))
4

您几乎可以使用 ipython 代码执行任何操作,您可以使用一个简单的 python 脚本执行。显然,使用 doctest 选项没有意义。

伪装饰器

以下是支持的装饰器及其采用的任何可选参数。一些装饰器可以用作整个块的选项(例如 verbatimsuppress),而一些装饰器仅适用于它们正下方的行(例如 savefig)。

@suppress

执行 ipython 输入块,但禁止呈现的输出中包含输入和输出块。此外,还可以将 :suppress: 作为指令选项应用于整个 .. ipython 块。

@verbatim

逐字插入输入和输出块,但自动增加行号。在内部,解释器将被馈送一个空字符串,因此它是一个保持行号一致的无操作。此外,还可以将 :verbatim: 作为指令选项应用于整个 .. ipython 块。

@savefig OUTFILE [IMAGE_OPTIONS]

将图形保存到静态目录并将其插入文档中,可能将其绑定到小型页面中和/或放置代码/图形标签/引用以关联代码和图形。采用要传递给图像指令的参数(scalewidth 等可以是关键字参数);有关详细信息,请参阅 图像选项

@doctest

将 ipython 块中粘贴的输出与文档构建时生成的输出进行比较,如果它们不匹配,则引发错误。此外,还可以将 :doctest: 作为指令选项应用于整个 .. ipython 块。

配置选项

ipython_savefig_dir

用于保存图形的目录。这是相对于 Sphinx 源目录的。默认值为 html_static_path

ipython_rgxin

编译的正则表达式,用于表示 IPython 输入行的开头。默认值为 re.compile('In [(d+)]:s?(.*)s*')。您不需要更改此值。

ipython_rgxout

编译的正则表达式,用于表示 IPython 输出行的开头。默认值为 re.compile('Out[(d+)]:s?(.*)s*')。您不需要更改此值。

ipython_promptin

表示生成的 ReST 中 IPython 输入提示符的字符串。默认值为 'In [%d]:'。这要求提示符中使用行号。

ipython_promptout

表示生成的 ReST 中 IPython 提示符的字符串。默认值为 'Out [%d]:'。这要求提示符中使用行号。

自动生成文档

Sphinx 指令,用于支持嵌入式 IPython 代码。

IPython 为 Sphinx 提供了一个扩展,用于突出显示和运行代码。

此指令允许粘贴整个交互式 IPython 会话(包括提示符),并且它们的代码将在文档构建时实际重新执行,所有提示符按顺序重新编号。它还允许您通过向指令提供参数 python 来输入代码作为纯 Python 输入。输出看起来像一个交互式 ipython 部分。

以下是一个示例,说明 IPython 指令如何在构建时运行 Python 代码。

In [1]: 1+1
Out[1]: 2

In [2]: import datetime
   ...: datetime.date.fromisoformat('2022-02-22')
   ...: 
Out[2]: datetime.date(2022, 2, 22)

它支持 IPython 结构,而纯 Python 不支持(例如魔术命令)

In [3]: import time

In [4]: %pdoc time.sleep
Class docstring:
    sleep(seconds)
    
    Delay execution for a given number of seconds.  The argument may be
    a floating point number for subsecond precision.
Call docstring:
    Call self as a function.

在使用 IPython 7.0+ 时,这也将支持顶级 async

In [5]: import asyncio
   ...: print('before')
   ...: await asyncio.sleep(1)
   ...: print('after')
   ...: 
before
after

命名空间将在多个代码块中保持不变,我们来定义一个变量

In [6]: who = "World"

现在打个招呼

In [7]: print('Hello,', who)
Hello, World

如果当前部分引发异常,您可以将 :okexcept: 标志添加到当前块,否则构建将失败。

In [8]: 1/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[8], line 1
----> 1 1/0

ZeroDivisionError: division by zero

IPython Sphinx 指令模块

要启用此指令,只需在 Sphinx conf.py 文件中列出它(确保您放置它的目录对 sphinx 可见,就像所有 Sphinx 指令所必需的那样)。例如,要启用语法突出显示和 IPython 指令

extensions = ['IPython.sphinxext.ipython_console_highlighting',
              'IPython.sphinxext.ipython_directive']

IPython 指令输出带有语言“ipython”的代码块。因此,如果您没有同时启用语法突出显示扩展,那么所有呈现的代码块都将是无色的。默认情况下,此指令假定您的提示符是未更改的 IPython 提示符,但可以对其进行自定义。可以在 conf.py 中放置的可配置选项为

ipython_savefig_dir

用于保存图形的目录。这是相对于 Sphinx 源目录的。默认值为 html_static_path

ipython_rgxin

编译的正则表达式,用于表示 IPython 输入行的开头。默认值为 re.compile('In \[(\d+)\]:\s?(.*)\s*')。您不需要更改此值。

ipython_warning_is_error: [默认为 True]

如果发生意外情况,则构建失败,例如,如果一个块引发异常但没有 :okexcept: 标志。被认为是严格的具体行为可能会在 sphinx 指令版本之间发生变化。

ipython_rgxout

编译的正则表达式,用于表示 IPython 输出行的开头。默认值为 re.compile('Out\[(\d+)\]:\s?(.*)\s*')。您不需要更改此值。

ipython_promptin

表示生成的 ReST 中 IPython 输入提示符的字符串。默认值为 'In [%d]:'。这要求提示符中使用行号。

ipython_promptout

表示生成的 ReST 中 IPython 提示符的字符串。默认值为 'Out [%d]:'。这要求提示符中使用行号。

ipython_mplbackend

指定嵌入式 Sphinx shell 是否应导入 Matplotlib 并设置后端的字符串。该值指定一个后端,该后端在 ipython_execlines 中的任何行执行之前传递给 matplotlib.use()。如果在 conf.py 中未指定,则使用默认值“agg”。要将 IPython 指令用作不依赖 matplotlib 的指令,请将该值设置为 None。如果用户在 ipython_execlines 中指定了 matplotlib 或使用了 @savefig 伪装饰器,则最终可能会导入 matplotlib。

ipython_execlines

将在嵌入式 Sphinx shell 中执行的字符串列表。典型用法是让某些包始终可用。如果您希望始终没有导入可用,请将其设置为一个空列表。如果在 conf.py 中指定为 None,则其效果是没有导入可用。如果从 conf.py 中完全省略,则使用默认值 [‘import numpy as np’, ‘import matplotlib.pyplot as plt’]。

ipython_holdcount

当使用 @suppress 伪装饰器时,执行计数可以增加或不增加。默认行为是保持执行计数,对应于 True 的值。将其设置为 False 以在每个被抑制的命令后增加执行计数。

例如,要在 matplotlib 不可用的情况下使用 IPython 指令,可以将后端设置为 None

ipython_mplbackend = None

指令的一个示例用法是

.. ipython::

    In [1]: x = 1

    In [2]: y = x**2

    In [3]: print(y)

请参阅 https://matplotlib.net.cn/sampledoc/ipython_directive.html 以获取其他文档。

伪装饰器

注意:每个输入仅支持一个装饰器。如果指定了多个装饰器,则仅使用最后一个装饰器。

除了上述链接中描述的伪装饰器/选项外,还进行了一些增强。如果代码执行导致异常或警告,该指令将在构建时向控制台发出消息。您可以通过指定 :okexcept: 或 :okwarning: 选项逐块抑制这些消息

.. ipython::
    :okexcept:
    :okwarning:

    In [1]: 1/0
    In [2]: # raise warning.

待办事项

  • 将临时 test() 函数变成一个真正的测试套件。

  • 将 ipython 特定功能从 matplotlib 内容中分解为更分离的代码。