如何在Sphinx Autodoc中移除与类名同名的模块名
问题场景与需求
我正在开发一个包含子包与模块的Python包,因部分模块体积过大需拆分,最终在特定子包中实现一个模块对应一个类的结构,示例包结构如下:
package ├── __init__.py ├── subpackage_1 │ ├── __init__.py │ ├── foo.py │ └── bar.py ├── subpackage_2 │ ├── __init__.py │ └── module_x.py ├── module_y.py └── ..
其中foo.py和bar.py各包含一个同名类:
# foo.py class Foo: pass
# bar.py class Bar: pass
为简化调用,在subpackage_1/__init__.py中导入并导出这些类:
# subpackage_1/__init__.py from .foo import Foo from .bar import Bar def __dir__(): return ['Foo', 'Bar']
编码时可通过package.subpackage_1.Foo直接访问类,但使用Sphinx Autodoc生成HTML文档时,类会显示为package.subpackage_1.foo.Foo。需要自动移除文档中所有与类名同名的模块名,使其显示为用户实际使用的调用路径。
解决方法
方法1:修改类的__module__属性
在子包的__init__.py中导入类后,直接修改类的__module__属性,让Sphinx识别其归属路径:
# subpackage_1/__init__.py from .foo import Foo from .bar import Bar # 将类的模块归属指向当前子包 Foo.__module__ = __name__ Bar.__module__ = __name__ def __dir__(): return ['Foo', 'Bar']
修改后,Sphinx会将类的归属路径识别为package.subpackage_1,生成的文档就会显示package.subpackage_1.Foo。
方法2:配置Sphinx别名(适合类数量少的场景)
在Sphinx的conf.py中添加以下配置,手动指定类的显示别名:
# conf.py autodoc_docstring_signature = False autodoc_type_aliases = { 'Foo': 'package.subpackage_1.Foo', 'Bar': 'package.subpackage_1.Bar' }
这种方法需要手动维护别名列表,适合类数量不多的项目。
方法3:自定义Sphinx扩展自动处理(适合类数量多的场景)
如果包中有大量这类“类与模块同名”的情况,可以编写一个简单的Sphinx扩展自动修正路径:
- 在Sphinx配置文件
conf.py所在目录创建fix_class_path.py文件:
from sphinx.ext.autodoc import ClassDocumenter class FixedClassDocumenter(ClassDocumenter): def add_directive_header(self, sig): class_name = self.object.__name__ module_path = self.object.__module__ # 检查类是否位于同名的子模块中(比如Foo在foo.py里,模块路径以.foo结尾) if module_path.endswith(f'.{class_name.lower()}'): # 将模块路径替换为父包路径 new_module_path = module_path.rsplit('.', 1)[0] self.object.__module__ = new_module_path super().add_directive_header(sig) def setup(app): app.add_autodocumenter(FixedClassDocumenter)
- 在
conf.py中加载这个扩展:
# conf.py extensions = [ 'sphinx.ext.autodoc', 'fix_class_path' ]
这个扩展会自动检测并修正所有符合“类名与所在模块名同名”的类的显示路径,无需手动修改每个类。
内容的提问来源于stack exchange,提问作者Worldsheep
相关产品推荐
相关产品推荐

