用Sphinx编写API文档¶
简介¶
本文档介绍如何在写代码的同时写下文档内容,并在后期用sphinx+restructuredText生成文档。本章主要介绍docstring和sphinx。
Docstring——将文档写在代码中¶
文档字符串(docstring)是书写在源代码中的文档,类似于注释。但它和注释及javadoc不一样,会在运行时中保留,这样在程序运行时也可以查看文档信息。
Python,Lisp和Julia等语言都支持这一功能。
在Python的交互式界面下,我们可以通过help()函数显示docstring。
>>> import requests
>>> help(requests.get)
Help on function get in module requests.api:
get(url, params=None, **kwargs)
Sends a GET request.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
Python中,docstring用三个引号引起来。位于文件开头则是对整个文件的说明。位于类或者函数下方则是对这两者的说明。
例如上面的代码显示的requests的get函数的说明在源代码中是这样保存的:
def get(url, params=None, **kwargs):
r"""Sends a GET request.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
kwargs.setdefault('allow_redirects', True)
return request('get', url, params=params, **kwargs)
我们可以分析一下docstring都由哪几部分组成。比如一个函数,一般由简介、参数、返回值和返回类型构成docstring的内容。
根据Python的PEP 257标准,python文件一般都要求有docstring。Docstring作为注释,可以使代码更容易被别人读懂。同时它也能方便的在Python终端中被调用。
Sphinx——文档生成工具¶
Sphinx是用来生成文档的工具,最初专门为Python设计,很多知名的Python项目都采用Sphinx编写的文档。
它使用reStructuredText这一标记语言写文档,可以输出多种格式,包括PDF、HTML和man page等等。Sphinx有apidoc这一扩展,可以自动从python源文件生成API文档。
Sphinx本身用Python编写,可以通过以下命令安装:
pip install -U Sphinx
以下是Sphinx生成的网页版文档的界面:
以下是一些使用Sphinx编写文档的项目链接:
- Python:https://docs.python.org/
- Python的第三方网络库requests:http://www.python-requests.org/en/master/
- 本地化工具Zanata:http://docs.zanata.org/en/release/
快速上手¶
这一章教您如何快速构建您的API文档。
创建一个sphinx项目¶
- 首先,我们运行 sphinx-quickstart 来自动创建一个sphinx项目。
你会被问到一些关于项目设置的问题,其中需要注意的是,您需要启用autodoc扩展。
Indicate which of the following Sphinx extensions should be enabled:
> autodoc: automatically insert docstrings from modules (y/n) [n]: y
> doctest: automatically test code snippets in doctest blocks (y/n) [n]:
...
如果您创建时没有选择启用autodoc,您也可以通过修改conf.py文件实现:需要修改extensions那个列表,加入以下内容:
sphinx.ext.autodoc',
- 运行如上命令后会生成一个文件夹,结构如下
目录
│ Makefile
│ make.bat
│
├─source
│ │ conf.py
│ │ index.rst
│ │
│ ├─_templates
│ └─_static
└─build
source文件夹是保存rst源文件的,build是保存生成的html和pdf等文件的,根据之前的设定,两个文件夹可以合并。
index.rst是项目的主文档,我们可以在其中的toctree里添加其它rst文件。
.. toctree::
:maxdepth: 2
usage/installation
usage/quickstart
...
- 生成文档。
在根目录下运行如下命令,可以选择不同的输出格式,比如以下命令会输出网页。
make html
基本的sphinx项目介绍就是这样,我们下一步讲解如何从含有docstring的源代码文件生成API文档。
自动生成API文档¶
我们需要使用sphinx-apidoc来代码文件生成对应rst文件,使用方法如下:
$ sphinx-apidoc [options] -o outputdir packagedir [pathnames]
比如我们把源代码放在source文件夹的getYiyi文件夹里,要在source文件夹下生成rst文件,则需要运行如下命令:
$ sphinx-apidoc -o ./ getYiyi
运行后会生成modules.rst和对应每个代码文件名rst文件。我们在index.rst里引用生成的modules文件即可以将生成的文档集成进来。
除此以外,我们还需要进行一些设置。
- 修改conf.py文件,将以下内容:
#import os
#import sys
#sys.path.insert(0, os.path.abspath(''))
修改为::
import os
import sys
sys.path.insert(0, os.path.abspath('./getYiyi'))
这是为sphinx指定了保存Python代码的路径。
警告
Sphinx需要导入python模块来提取docstring,所以一定要记着加上 if __name__ == ‘__main__’ 这一条件。
如果你还想添加查看源代码的功能,需要在extension里加入 'sphinx.ext.viewcode',
。
最后生成的结果如下:
文档内容可以在Indices and tables中进行检索。
ApiDoc使用的指令¶
打开生成的代码的rst文件,可以看到如下内容:
getYiyi
==============
.. automodule:: getYiyi
:members:
:undoc-members:
:show-inheritance:
automodule指令会自动生成所有的class、function和exception等内容。可以在它下面的members里指定要生成的对象。 使用 :undoc-members:
后,没有docstirng的部分也会得到处理。 :show-inheritance:
用来显示基类的信息。
使用如下的autoclass
.. autoclass:: Noodle
:members:
则不会对私有的方法(以_开始和结束)做处理。如果要记录私有的方法和属性,可以使用 :private-members:
。要记录特殊对象(以__开始和结束),可以使用 :special-members:
。
更多参见sphinx官网:http://www.sphinx-doc.org/en/master/ext/autodoc.html
用restructuredText自己撰写文档¶
自动生成的API文档可能比较简单,我们会需要自己补充一些内容,这时就需要我们用restructuredText进行写作了。
restructuredText是Sphinx默认使用的写作语言,可以让我们像写代码一样来进行文档的创作。
段落¶
段落是rst中的基本单位,每个段落需要有一个空行分割。
列表¶
无序列表用星号开头,有序列表可以用数字或者井号开头。
* This is a bulleted list.
* It has two items, the second
item uses two lines.
1. This is a numbered list.
2. It has two items too.
#. This is a numbered list.
#. It has two items too.
定义列表则使用缩进来实现:
term
Description.
分级¶
rst使用以下形式表示标题:
=================
This is a heading
=================
使用不同的符号表示不同的等级,但不限定每级使用什么符号。推荐使用如下标准:
- # 用于部分
- * 用于章节
- = 一级标题
- - 二级标题
- ^ 三级标题
代码块¶
在段落后面加上::,代码需要空一行并缩进后输入在后面。默认支持python代码的高亮显示。我们也可以用code-block指令来引用代码。
代码对象¶
我们可以通过以下方式来记录一个python函数::
.. py:function:: enumerate(sequence[, start=0])
Return an iterator that yields tuples of an index and an item of the
*sequence*. (And so on.)
结果:
-
enumerate
(sequence[, start=0])¶ Return an iterator that yields tuples of an index and an item of the sequence. (And so on.)
除了 py:function
,还可以使用 py:class
和 py:method
。
我们可以用 :py:func:
角色来进行引用::
The :py:func:`enumerate` function can be used for ...
效果:enumerate()
指令¶
Directives是Roles之外的另一个rst使用的显式标记,用以拓展它的功能。Directive block包含三个部分:参数(arguments),选项(options,一个rst语法表示的列表),内容(content)。
它的结构通常是这样的::
+-------+-------------------------------+
| ".. " | directive type "::" directive |
+-------+ block |
| |
+-------------------------------+
比如插入一个图片::
.. image:: http://www.w3school.com.cn//i/eg_tulip.jpg

插入一个危险提示::
.. DANGER::
Beware killer rabbits!
危险
Beware killer rabbits!
插入一个csv表格::
.. csv-table:: Frozen Delights!
:header: "Treat", "Quantity", "Description"
:widths: 15, 10, 30
"Albatross", 2.99, "On a stick!"
"Crunchy Frog", 1.49, "If we took the bones out, it wouldn't be crunchy, now would it?"
Treat | Quantity | Description |
---|---|---|
Albatross | 2.99 | On a stick! |
Crunchy Frog | 1.49 | If we took the bones out, it wouldn’t be crunchy, now would it? |
sphinx给rst添加了一个toctree指令,用来安排目录。它可以连接不同的文件,使得我们可以把内容写在不同的文件里。:
.. toctree::
:maxdepth: 2
usage/installation
usage/quickstart
...
更多¶
生成中文PDF¶
Sphinx是将rst文件转为latex文件以生成pdf的,装好latex后,在项目目录下运行make latexpdf就可以生成了。
以下是一些注意事项,主要是conf.py的修改:
- 修改latex_elements里的preamble,添加ctex或者cjk宏包可以支持中文。
- 修改language可以更改默认的语言,在生成的tex文件中会使用renewcommand修改原来的日期等信息为对应语言的。但默认中文的章节名没有得到更改,可以用以下代码不显示英文的Chapter。注意latex里有很多斜杠,在python中需要在引号前加r以避免转义。
'preamble': r'''
\addto\captionsenglish{\renewcommand{\chaptername}{}}
\usepackage[UTF8, scheme = plain]{ctex}
''',
更换网页主题¶
修改conf.py文件的 html_theme = 'alabaster'
可以换主题。更多设置可以在此找到:http://www.sphinx-doc.org/en/stable/theming.html
使用readthedocs托管文档¶
readthedocs是一个文档托管平台,很多著名的python项目都将文档托管在这上面。
我们将项目传到github上,再在readthedocs中绑定该项目。这样就有了一个持续集成环境。每次修改被提交到github上,readthedocs就会基于最新的项目构建一次网页和PDF。
使用Markdown¶
Markdown是比restructuredText更加轻量的标记语言。Sphinx支持用Markdown进行写作。
启用Markdown需要如下步骤:
安装recommonmark::
pip install recommonmark
添加如下内容到conf.py中::
source_parsers = { '.md': 'recommonmark.parser.CommonMarkParser', }
添加Markdown的文件扩展名到配置文件的source_suffix变量::
source_suffix = ['.rst', '.md']
给其它语言生成API文档¶
Sphinx默认支持生成Python的API文档,但对于其它语言的支持不佳。有一款Sphinx的扩展,叫做Breathe,便可以使Sphinx支持其它语言。
Breathe是Sphinx和Doxygen这两个文档工具的桥梁,这样Doxygen支持的语言也可以用到Sphinx当中。而Doxygen支持的语言就比较广泛了:
- C, C++
- Objective-C
- C#
- PHP
- Java
- Python
- IDL (Corba, Microsoft, and UNO/OpenOffice flavors)
- Fortran
- VHDL
- Tcl
- D
更多见Breathe的主页:http://breathe.readthedocs.io/en/latest/
本地化文档¶
Sphinx支持使用gettext以支持项目的本地化。gettext是本地化常用的一个标准。
下图是一个Sphinx本地化的大致流程:

以下是具体操作方法:
用
pip install sphinx-intl
命令安装sphinx-intl。在conf.py文件中添加以下配置::
locale_dirs = ['locale/'] # path is example but recommended. gettext_compact = False # optional.
生成gettext的pot文件::
make gettext
创建或者更新locale文件夹,这里我们可以指定目标语言::
sphinx-intl update -p _build/gettext -l en
翻译上一步在locale/en/LC_MESSAGES文件夹下生成的po文件。
生成翻译的文档::
make -e SPHINXOPTS="-D language='en'" html
或者直接使用 sphinx-build 来生成在指定文件夹::
sphinx-build -M html source en -D language=en
REST API¶
你可以用Sphinx来手写API文档,但更加推荐使用支持OpenAPI规范的专门的REST API工具,比如国内阿里的rap和开源的Swagger。
Swagger有以下几点好处:
- Swagger 可以生成一个具有互动性的API控制台,开发者可以用来快速学习和尝试API。
- Swagger 可以生成客户端SDK代码用于各种不同的平台上的实现。
- Swagger 文件可以在许多不同的平台上从代码注释中自动生成。
- Swagger 有一个强大的社区,里面有许多强悍的贡献者。
这里是一个详细的REST API文档编写教程:http://idratherbewriting.com/learnapidoc/
参考文献¶
本教程的编写参考了网络上的资源,在此进行记录。
- sphinx-apidoc:http://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html
- Docstring https://en.wikipedia.org/wiki/Docstring