python sphinx-autodoc
## 关于Sphinx的autodoc这里有些你可能没注意到的细节接手过几个遗留的Python项目最让人头疼的往往不是代码有多烂而是文档和代码完全对不上。文档里写的参数名在代码里根本不存在或者模块明明已经重写了三版文档还停留在第一版。这时候就会特别想念自动生成文档的工具而Sphinx autodoc就是其中绕不开的一个选择。它到底是什么Sphinx autodoc严格来说不算一个独立的工具它是Sphinx文档生成器的一个扩展插件。Sphinx自己的强项是处理rst或者MyST格式的文档文件但autodoc解决了另一个痛点——直接从Python源码里提取文档字符串docstring转换成文档页面。可以把这个过程想象成装修房子。Sphinx是施工队它能按照设计图纸rst文件搭建整个房子。而autodoc就像是一个自动化的量尺它直接从代码墙上读取标注docstring然后告诉施工队该在哪里贴标签、写说明。这样做的好处很明显——代码改动了docstring文档自然跟着更新从根本上杜绝了“两个人各说各话”的情况。它能做什么做到什么程度autodoc最基础的功能是扫描Python模块、类、函数、方法的docstring把它们变成结构化的文档。但深入用下去会发现它其实有一些挺实用的细节自动推导类型如果函数写了类型注解比如def process(name: str) - list:autodoc会自动把类型信息展示出来不用在docstring里重复写类型。这比纯依赖docstring文本更可靠因为类型注解是代码的一部分更容易保持同步。控制文档展示的颗粒度可以用autoclass、autofunction这些指令独立控制每个元素的展示方式。比如想展示类的所有静态方法但隐藏私有方法可以在配置里指定exclude-members。模块级的文档不仅仅能生成类和函数的文档还能提取模块的__doc__作为模块说明这对于组织大型项目特别有用。和Sphinx其他扩展配合比如配合napoleon扩展可以解析Google风格的docstring配合viewcode可以直接跳转到源代码。这些配合在实战中往往比单独用autodoc顺手得多。怎么用起来最基本的用法其实挺简单的。首先确保安装了sphinx和sphinx-autodoc有时候带着sphinx.autodoc其实是Sphinx自带的但旧版本可能需要单独装pip install sphinx sphinx-rtd-theme在Sphinx的conf.py里加上扩展extensions[sphinx.ext.autodoc,# 其他扩展...]然后在rst文件里使用指令.. automodule:: my_project.core :members: :undoc-members: :show-inheritance: .. autoclass:: my_project.core.DataProcessor :members: :private-members:这里面:members:表示展示所有公共成员:undoc-members:连没有docstring的也展示出来有时候参数和函数签名本身就足够说明问题这在工具脚本里很实用:show-inheritance:显示继承关系。一个常见的坑是autodoc需要导入模块来读取docstring所以如果项目里有在模块顶层执行的文件操作或数据库连接运行Sphinx构建就会报错。解决办法是在conf.py里设置autodoc_mock_imports把那些没什么实际意义的第三方库mock掉。最佳实践用的时间长了摸索出几个比较实用的做法docstring的写法直接决定输出质量。autodoc能把docstring原样搬到文档里所以写docstring时要想着“这段文字会在文档里出现”而不仅仅是给开发者看。多写些使用场景和边界条件少写那些“这个函数做什么”的重复废话。比如defcalculate_discount(price:float,rate:float0.1)-float: 计算商品折后价格。 参数 price 应大于零rate 应在 0 到 1 之间。如果 rate 为 0.15 表示打 8.5 折。返回结果保留两位小数。 :param price: 原价 :param rate: 折扣率默认 0.19折 :return: 折后价格 利用好autodoc_default_options。在conf.py里设置一次就不用每个rst文件都重复写选项autodoc_default_options{members:True,member-order:bysource,special-members:__init__,undoc-members:True,exclude-members:__weakref__}分模块组织文档。不要试图用一个rst文件塞下整个项目建议一个模块对应一个rst文件然后用toctree串起来。这样维护时清晰构建时间也能接受。配合类型注解。autodoc对Python 3.5的类型注解支持良好建议多用。比如用Optional[str]而不是Union[str, None]能更直观autodoc也能正确渲染。和同类技术对比市面上能做类似事情的工具其实不多主要是pydoc和MkDocs。简单对比一下各自的特点和标准库pydoc比较pydoc是Python自带的用python -m pydoc -p 8080就能开一个简单的HTTP服务查看文档。优点是零依赖但功能实在太简陋。它只能展示当前源码里的信息没法加额外的说明文字。而且生成的文档没法定制主题看起来永远是那个朴素的HTML风格。如果文档需求只是给自己快速查一查pydoc够用。但要是给用户或团队成员看还是得用Sphinx autodoc。和MkDocs比较MkDocs是用Markdown写文档配合mkdocstrings插件也能提取docstring。MkDocs的优势是上手特别快不需要学rst语法对习惯Markdown的开发者很友好。但MkDocstrings在提取复杂类型信息时不如Sphinx autodoc准确特别是涉及到泛型、多态的情况。Sphinx在这方面根基更稳因为它本身就是为Python设计的对Python类型系统的理解更深。一个现实的选择小型工具库或者内部项目用MkDocsmkdocstrings就挺好每天写文档压力小。但一旦项目大了需要细粒度控制文档结构比如把文档切分成教程、API参考、设计说明等不同章节或者要生成PDF版本Sphinx autodoc的优势就体现出来了。它虽然学习曲线比MkDocs陡一点但后期扩展性和灵活性更强。记得有个朋友维护着一个中等规模的Python库文档一直用Sphinx autodoc生成。有次他们重构了部分API改完代码后跑一遍Sphinx build文档自动更新了所有函数签名和参数说明只花几分钟。而另一个用纯手工写文档的项目一个参数名修改可能要翻遍几十个文件。这种差异在维护阶段慢慢会放大很多倍。