【问题标题】:How do I document classes without the module name?如何在没有模块名称的情况下记录类?
【发布时间】:2013-02-27 15:10:07
【问题描述】:

我正在尝试使用sphinx 记录一个python 包并成功生成了html 文件。我正在记录的包由一组*.py 文件组成,其中大多数包含一个类,其中几个文件是定义了函数的真正模块。我不需要公开每个类都在一个模块中的事实,因此我在__init__.py 文件中添加了合适的from 语句,例如

from base import Base

这样用户就可以使用import pkg 命令,而不必指定包含该类的模块:

import pkg
class MyBase(pkg.Base):  # instead of pkg.base.Base ...
...

问题在于 sphinx 坚持将类记录为 pkg.base.Base。我试图在conf.py 中设置add_module_names = False。然而,这会导致 sphinx 将类显示为简单的 Base 而不是 pkg.Base。此外,这也破坏了两个 模块的 *.py 文件的文档。

如何让sphinx 将类显示为pkg.Base? 以及如何为每个*.py 文件选择性地设置add_module_names 指令?

【问题讨论】:

  • 不要那样做。 Sphinx 正确地 告诉用户类在哪里定义,而不是在哪里导入。如果你在两个不同的模块中导入Base 类,Sphinx 怎么知道你想使用哪个名字?如果您不希望用户知道您定义类的模块,那么您可能应该将其设为私有(如果我没记错的话,它不会显示在生成的文件中)。
  • @Bakuriu - 不确定我是否理解您的评论。澄清一下,每个类都在一个单独的文件中的唯一原因是为了更容易管理源代码控制。类的使用只需要包名和类名,而不需要模块名(这是多余的)。文档应该描述用法而不是定义,你不觉得吗?如何将模块名称设为私有?
  • 那有什么问题呢?只需使用add_module_names = False 并将文档放在正确的页面中。用户将看到在引用模块pkg 的页面中有一个文档类Base,这很好。 pkg.module.Base only 指的是定义类的模块,而不是您“使用它”的模块(这是未明确定义的)。如果你想要一个肮脏的解决方案来获得你想要的输出,那么在__init__创建一个假子类:class TheClass(pkg.module.TheClass): pass,继承文档。

标签: python python-sphinx


【解决方案1】:

这是完成 OP 要求的一种方法:

  1. pkg/__init__.py 中添加__all__ 列表:

    from base import Base    # Or use 'from base import *'
    
    __all__ = ["Base"]
    
  2. 在 .rst 文件中使用 .. automodule:: pkg

Sphinx 现在将输出文档,其中类名显示为 pkg.Base 而不是 pkg.base.Base

【讨论】:

  • 这样做的问题是,如果Base 继承自同样在base 中定义的基类,则 sphinx 继承链接将被破坏。
  • 您的意思是Base 的“基础”是pkg.base.ParentClass 而不是pkg.ParentClass
  • 是的,我就是这个意思。我确实看到了,但是从所有基类中操作所有__module__ 对我来说似乎太冒险了。特别是因为其中一些是 cython 代码,我想知道它是否会破坏 autodoc 能够定位要解析的源。
【解决方案2】:

我已将我找到的答案整合到一个可扩展的外形尺寸中:

my_project/
    __init__.py
    mess.py
  • mess.py:
class MyClass:
    pass

class MyOtherClass(MyClass):
    pass
  • __init__.py:
from .mess import MyClass, MyOtherClass

__all_exports = [MyClass, MyOtherClass]

for e in __all_exports:
    e.__module__ = __name__

__all__ = [e.__name__ for e in __all_exports]

这对我来说似乎效果很好。

【讨论】:

  • 当您使用from .mess import * 而不是明确命名要导入的内容时,您会如何意识到这一点?
  • 我避免 * 导入,所以我什至没有考虑这个,我不确定什么是最好的解决方案。
【解决方案3】:

我想提供一个更通用的方法。

变量__all__是根据dir()填充的。但子包名称(此处为 mypackage)和所有内置属性(以 __ 开头)被忽略。

from .mypackage import *

__all__ = []
for v in dir():
    if not v.startswith('__') and v != 'mypackage':
        __all__.append(v)

【讨论】:

    【解决方案4】:

    简短的回答:你不应该。只需将狮身人面像指向您的代码目录即可。 Sphinx 记录代码并显示模块层次结构。最终如何导入模块完全由开发人员掌握,而不是文档工具的责任。

    【讨论】:

    • 我不同意。文档应该反映库作者想要的包结构。
    猜你喜欢
    • 1970-01-01
    • 2011-02-11
    • 2020-05-22
    • 1970-01-01
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    相关资源
    最近更新 更多