Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 287 – reStructuredText 文档字符串格式

作者:
David Goodger <goodger at python.org>
讨论列表:
Doc-SIG 列表
状态:
活跃
类型:
信息
创建日期:
2002-03-25
更新历史:
2002-04-02
替换:
216

目录

摘要

当纯文本不足以表达内联文档时,Python 程序员一直在寻找一种用于文档字符串的格式。本 PEP 建议将 reStructuredText 标记语言 作为 Python 文档字符串中结构化纯文本文档的标准标记格式,以及 PEP 和辅助文档的标准格式。reStructuredText 是一种丰富且可扩展的标记语言,但它易于阅读,并且具有所见即所得的纯文本标记语法。

本文档仅涉及文档字符串的低级语法。本 PEP 并不涉及文档字符串的语义或处理(有关“文档字符串 PEP 路线图”,请参阅 PEP 256)。本 PEP 也不是为了废弃纯文本文档字符串,纯文本文档字符串始终都是合法的。reStructuredText 标记语言是为那些想要更具表现力的文档字符串的人提供的替代方案。

优势

程序员天生懒惰。我们使用函数、类、模块和子系统来重用代码。通过其文档字符串语法,Python 允许我们从内部对代码进行文档化。Python 文档兴趣小组(Doc-SIG)的“圣杯”一直是标记语法和工具集,用于实现自动文档化,即可以从 Python 系统的文档字符串中提取并处理上下文信息,并将其转换为适用于多种用途的实用高质量文档。

文档标记语言有三种用户:编写文档的作者、处理数据的软件系统以及读者,读者是最终用户,也是最重要的用户群体。大多数标记语言都是为作者和软件系统设计的;读者只能看到处理后的形式,无论是纸质形式还是通过浏览器软件。reStructuredText 与众不同:它旨在易于在源代码形式下阅读,无需事先了解标记语言。reStructuredText 可以在纯文本格式下完全阅读,并且许多标记形式与常见用法相匹配(例如,*emphasis*),因此读起来非常自然。然而,它足够丰富,可以生成复杂的文档,并且可扩展,因此几乎没有限制。当然,要编写 reStructuredText 文档,需要事先了解一些知识。

该标记语言提供了功能和表现力,同时在源文本中保持了易读性。处理后的形式(HTML 等)使所有内容对读者都可访问:内联实时超链接;到脚注的实时链接以及从脚注的实时链接;自动目录(包含实时链接!);表格;用于图表等的图像;美观易读的样式化文本。

reStructuredText 解析器现已推出,它是 Docutils 项目的一部分。独立的 reStructuredText 文档和 PEP 可以转换为 HTML;其他输出格式编写器正在开发中,并将在未来一段时间内提供。正在开发 Python 源代码“阅读器”,它将实现从文档字符串进行自动文档化。鼓励现有自动文档工具的作者将 reStructuredText 解析器集成到他们的项目中,或者更好的是,共同努力为 Python 标准库开发一套世界一流的工具集。

在不久的将来,将提供工具,允许程序员为在线帮助生成 HTML,为多种用途生成 XML,最终为印刷文档生成 PDF、DocBook 和 LaTeX,这些功能基本上是“免费”的,只需使用现有的文档字符串即可。采用标准至少会使文档字符串处理工具受益,避免进一步“重复造轮子”。

最终,现有的标准自动文档工具 PyDoc 可以添加 reStructuredText 支持。在过渡期间,它不会对 reStructuredText 标记有任何问题,因为它将所有文档字符串视为预格式化的纯文本。

目标

以下是一些普遍接受的文档字符串格式目标,这些目标是在 Doc-SIG 中讨论的。

  1. 它必须在源代码形式下易于被普通读者阅读。
  2. 它必须易于在任何标准文本编辑器中输入。
  3. 它不应包含可以通过解析模块推断出的信息。
  4. 它必须包含足够的信息(结构),以便可以将其转换为任何合理的标记格式。
  5. 它必须能够在文档字符串中编写模块的全部文档,而不会受到标记语言的限制。

reStructuredText 满足并超越了所有这些目标,并设置了自己的目标,甚至更加严格。请参阅下面的 文档字符串相关功能

本 PEP 的目标如下:

  1. 将 reStructuredText 建立为文档字符串(Python 模块和包的内联文档)、PEP、README 类型文件和其他独立文档的标准结构化纯文本格式。“接受”状态将通过 Python 社区共识和最终的 BDFL 声明来寻求。

    请注意,reStructuredText 被提议为一种标准,而不是唯一的标准。使用它是完全可选的。那些不想使用它的人可以不使用。

  2. 征求并解决 Python 社区提出的任何相关问题。
  3. 鼓励社区支持。只要存在多个竞争的标记语言,开发社区就会出现分裂。一旦存在标准,人们就会开始使用它,势头也会随之产生。
  4. 整合来自相关自动文档项目的努力。希望感兴趣的开发者能够共同努力,开发一个联合/合并/通用实现。

一旦 reStructuredText 成为 Python 标准,就可以将精力集中在工具上,而不是争论标准。Python 需要一套标准的文档工具。

关于 PEP,可以应用以下一种或两种策略:

  1. 保留现有的 PEP 部分结构构造(单行部分标题、缩进正文文本)。可以禁止子部分,或者在缩进正文文本中使用 reStructuredText 样式的下划线标题来支持子部分。
  2. 将 PEP 部分结构构造替换为 reStructuredText 语法。部分标题需要下划线,子部分将开箱即用地支持,正文文本无需缩进(除了块引用)。

推荐策略 (b),并且已完成其实施。

RFC 2822 标头的支持已添加到 reStructuredText 解析器中,用于 PEP(在特定上下文中是明确的:文档的第一个连续块)。可能需要明确指定允许用于 PEP 部分标题的过/下划线样式,以确保一致性。

理由

缺少文档字符串的标准语法阻碍了开发标准工具,这些工具用于将文档字符串提取并转换为标准格式的文档(例如,HTML、DocBook、TeX)。已经提出了许多标记格式和变体,以及与这些提案相关的许多工具,但是没有标准的文档字符串格式,它们未能获得强大的追随者,或者中途夭折。

在 Doc-SIG 存在的整个过程中,从未达成关于单个标准文档字符串格式的共识。一直以来,人们都在寻求一种轻量级、隐式标记语言,原因如下(除其他原因外):

  1. 在 Python 代码中编写的文档字符串可在交互式解释器中获得,并且可以“打印”。因此使用纯文本以确保易读性。
  2. 程序员希望在不牺牲原始文档字符串可读性的情况下,为其文档字符串添加结构。未修饰的纯文本无法转换为(“向上转换”)有用的结构化格式。
  3. 显式标记(如 XML 或 TeX)被广泛认为不适合没有经验的人阅读。
  4. 隐式标记在美学上与简洁的 Python 语法相兼容。

多年来,在 Doc-SIG 上已经提出了许多用于文档字符串的替代标记语言;下面列出了一个代表性样本。针对上面陈述的目标,对每种标记语言进行了简要分析。请注意,这不是所有现有标记系统的排他性列表;还有许多其他标记语言(Texinfo、Doxygen、TIM、YODL、AFT,……)未被提及。

  • XMLSGMLDocBookHTMLXHTML

    XML 和 SGML 是显式、格式良好的元语言,适用于各种文档。XML 是 SGML 的一个变体。它们最好用在幕后,因为对于没有经验的人来说,它们冗长、难以输入,并且过于杂乱,难以舒适地作为源代码阅读。DocBook、HTML 和 XHTML 都是 SGML 和/或 XML 的应用程序,它们都具有相同的基本语法和相同的缺点。

  • TeX

    TeX 与 XML/SGML 类似,它也是显式的,但不太容易编写,也不太容易被没有经验的人阅读。

  • Perl POD

    大多数 Perl 模块都使用名为 POD(Plain Old Documentation)的格式进行文档化。这是一种易于输入的非常低级的格式,与 Perl 解析器高度集成。许多工具可以将 POD 文档转换为其他格式:info、HTML 和手册页,等等。然而,POD 语法在可读性方面类似于 Perl 本身。

  • JavaDoc

    Java 类和函数前面的特殊注释用于对代码进行文档化。提取这些注释并将其转换为 HTML 文档的程序称为 javadoc,它是标准 Java 发行版的一部分。但是,JavaDoc 与 HTML 关系密切,使用 HTML 标签进行大多数标记。因此,它也具有 HTML 的可读性问题。

  • SetextStructuredText

    早期,曾有人提出过 Setext(Structure Enhanced Text)的变体(包括 Zope Corp 的 StructuredText),用于 Python 文档字符串格式化。以下将这些变体统称为“STexts”。STexts 的优点是易于阅读,无需特殊知识,并且相对易于编写。

    尽管一些人(包括大多数现有的 Python 自动文档工具)使用了 STexts,但直到现在,STexts 始终未能成为标准,原因如下:

    • STexts 不完整。由于缺少人们希望在文档字符串中使用的“基本”构造,STexts 的理想程度降低了。请注意,这些“基本”构造并非普遍存在;每个人都有自己的需求。
    • STexts 有时令人惊讶。某些文本片段被意外地解释为标记,导致用户感到沮丧。
    • SText 实现存在错误。
    • 大多数 STexts 除了实现本身外,没有正式的规范。有错误的实现意味着有错误的规范,反之亦然。
    • 当在非标记上下文中使用标记字符时,没有机制可以绕过 SText 标记规则。换句话说,没有办法转义标记。

隐式 SText 的支持者强烈反对显式标记(XML、HTML、TeX、POD 等)的提议,并且这场辩论从 1996 年或更早的时候就断断续续地持续着。

reStructuredText 是对 SText 概念的彻底修改和重新解释,解决了上面列出的所有问题。

规范

reStructuredText 的规范和用户文档非常广泛。这里不重复或总结所有内容,而是提供指向原始文档的链接。

请先查看 reStructuredText 简介,这是一个简短而友好的介绍。 reStructuredText 快速参考 用户参考快速总结了所有标记结构。有关完整和详细的信息,请参阅以下文档

此外,StructuredText 的问题 解释了关于 StructuredText 的许多标记决策,以及 reStructuredText 语法备选方案记录 记录了独立做出的标记决策。

文档字符串相关功能

  • 标记转义机制。

    反斜杠(\)用于在需要时转义标记字符,以用于非标记目的。但是,内联标记识别规则是经过构建的,以最大程度地减少对反斜杠转义的需要。例如,尽管星号用于 *强调*,但在非标记上下文中,例如“*”或“(*)”或“x * y”,星号不会被解释为标记,并且保持不变。对于反斜杠的许多非标记用途(例如,描述正则表达式),内联文字或文字块适用;请参阅下一项。

  • 用于包含 Python 源代码和 Python 交互式会话的标记:内联文字、文字块和 doctest 块。

    内联文字使用 双反引号 来指示程序 I/O 或代码片段。在内联文字中不进行任何标记解释(包括反斜杠转义 [\] 解释)。

    文字块(块级文字文本,例如代码摘录或 ASCII 图形)是缩进的,并在前一段的末尾用双冒号 (“::”) 表示(就在这里 ->)

    if literal_block:
        text = 'is left as-is'
        spaces_and_linebreaks = 'are preserved'
        markup_processing = None
    

    Doctest 块以 “>>> “ 开头,以空行结尾。不需要缩进或文字块双冒号。例如

    Here's a doctest block:
    
    >>> print 'Python-specific usage examples; begun with ">>>"'
    Python-specific usage examples; begun with ">>>"
    >>> print '(cut and pasted from interactive sessions)'
    (cut and pasted from interactive sessions)
    
  • 隔离 Python 标识符的标记:解释文本。

    用单反引号括起来的文本被识别为“解释文本”,其解释取决于应用程序。在 Python 文档字符串的上下文中,解释文本的默认解释是作为 Python 标识符。文本将用指向给定标识符文档的超链接进行标记。查找规则与 Python 本身相同:LGB 命名空间查找(本地、全局、内置)。解释文本的“角色”(标识类、模块、函数等)是根据命名空间查找隐式确定的。例如

    class Keeper(Storer):
    
        """
        Keep data fresher longer.
    
        Extend `Storer`.  Class attribute `instances` keeps track
        of the number of `Keeper` objects instantiated.
        """
    
        instances = 0
        """How many `Keeper` objects are there?"""
    
        def __init__(self):
            """
            Extend `Storer.__init__()` to keep track of
            instances.  Keep count in `self.instances` and data
            in `self.data`.
            """
            Storer.__init__(self)
            self.instances += 1
    
            self.data = []
            """Store data in a list, most recent last."""
    
        def storedata(self, data):
            """
            Extend `Storer.storedata()`; append new `data` to a
            list (in `self.data`).
            """
            self.data = data
    

    每个解释文本片段都根据包含其文档字符串的块的本地命名空间进行查找。

  • 隔离 Python 标识符并指定其类型的标记:带角色的解释文本。

    虽然 Python 源代码上下文读取器旨在不需要显式角色,但它们可以使用。为了显式地对标识符进行分类,角色与标识符一起以前缀或后缀形式给出

    Use :method:`Keeper.storedata` to store the object's data in
    `Keeper.data`:instance_attribute:.
    

    为角色选择的语法很冗长,但这是必要的(如果有人有更好的选择,请将其发布到 Doc-SIG)。标记的意图是应该很少需要使用显式角色;他们的使用应保持在绝对最低限度。

  • 用于“标记列表”或“标签列表”的标记:字段列表。

    字段列表表示从字段名到字段体的映射。它们主要用于扩展语法,例如“书目字段列表”(表示文档元数据,例如作者、日期和版本)和指令的扩展属性(见下文)。它们可用于实施方法(文档字符串语义),例如标识参数、引发的异常等;此类用法超出了本 PEP 的范围。

    使用修改后的 RFC 2822 语法,在字段名前后都有冒号。字段体也更通用;它们可以包含多个字段体(甚至嵌套字段列表)。例如

    :Date: 2002-03-22
    :Version: 1
    :Authors:
        - Me
        - Myself
        - I
    

    标准的 RFC 2822 头部语法不能用于此结构,因为它存在歧义。一个单词后跟冒号出现在一行的开头在书面文本中很常见。

  • 标记可扩展性:指令和替换。

    指令用作 reStructuredText 的扩展机制,一种在不添加新语法的情况下添加对新块级结构支持的方法。图像、警告(注意、警告等)和目录生成(以及其他)的指令已实现。例如,以下是放置图像的方法

    .. image:: mylogo.png
    

    替换定义允许块级指令的强大功能和灵活性与内联文本共享。例如

    The |biohazard| symbol must be used on containers used to
    dispose of medical waste.
    
    .. |biohazard| image:: biohazard.png
    
  • 节结构标记。

    reStructuredText 中的节标题使用下划线(以及可能的上划线)来装饰,而不是缩进。例如

    This is a Section Title
    =======================
    
    This is a Subsection Title
    --------------------------
    
    This paragraph is in the subsection.
    
    This is Another Section Title
    =============================
    
    This paragraph is in the second section.
    

问答

  1. reStructuredText 足够丰富吗?

    是的,对于大多数人来说足够了。如果它缺少特定应用程序所需的某些结构,则可以通过指令机制添加它。如果忽略了有用且常见的结构并且可以找到合适的可读语法,则可以将其添加到规范和解析器中。

  2. reStructuredText *太*丰富了吗?

    对于特定的应用程序或个人来说,也许。总的来说,没有。

    从一开始,只要有人在 Doc-SIG 上提出文档字符串标记语法,就会有人抱怨缺乏对某些结构的支持。回复通常是类似“我们谈论的是文档字符串,文档字符串不应该有复杂的标记”。问题是,对一个人来说似乎多余的结构,对另一个人来说可能是绝对必要的。

    reStructuredText 采取相反的方法:它提供了一组丰富的隐式标记结构(加上用于显式标记的通用扩展机制),允许各种类型的文档。如果结构集对于特定应用程序来说太丰富,则可以从解析器中删除未使用的结构(通过特定于应用程序的覆盖),或者简单地通过约定省略它们。

  3. 为什么不用缩进来表示节结构,就像 StructuredText 所做的那样?这不是更“Pythonic”吗?

    Guido van Rossum 在 2001 年 6 月 13 日的 Doc-SIG 帖子中写道

    我仍然认为使用缩进来表示分节是错误的。如果你看看真实书籍和其他印刷出版物的版式,你会注意到缩进经常使用,但主要是在节内级别。缩进可以用来偏移列表、表格、引用、示例等。(文档字符串不同的论点是它们是文本格式化程序的输入是错误的:重点是它们在未经处理的情况下也是可读的。)

    我拒绝使用缩进是 Pythonic 的论点:文本不是代码,不同的传统和约定适用。人们已经为了可读性而展示文本超过 30 个世纪。我们不要不必要地创新。

    请参阅 通过缩进表示节结构StructuredText 的问题 中进一步阐述。

  4. 为什么将 reStructuredText 用于 PEP?现有标准有什么问题?

    现有 PEP 标准在通用表达能力方面非常有限,并且对于这种参考丰富的文档类型来说,引用尤其缺乏。PEP 目前已转换为 HTML,但结果(主要是等宽文本)不太吸引人,并且 HTML 的大部分增值潜力(尤其是内联超链接)尚未得到利用。

    将 reStructuredText 作为 PEP 的标准标记将能够实现更丰富的表达,包括对节结构、内联标记、图形和表格的支持。在几个 PEP 中有 ASCII 图形图表,这是纯文本文档所能支持的全部。由于 PEP 以 HTML 形式提供,因此能够包含适当的图表将立即有用。

    当前的 PEP 实践允许在文本中使用“[1]”形式的参考标记,并且脚注/参考本身列在文档末尾的某个部分。目前,参考标记和脚注/参考本身之间没有超链接(可以在 pep2html.py 中添加它,但“标记”本身存在歧义,并且不可避免地会发生错误)。一个包含很多参考的 PEP(比如这个 ;-) 需要来回翻阅很多次。在修改 PEP 时,通常会添加新的参考或删除未使用的参考。重新编号参考很痛苦,因为它必须在两个地方进行,并且会产生级联效应(插入一个新的参考 1,其他所有参考都必须重新编号;始终将新的参考添加到末尾是最优的)。参考很容易不同步。

    PEP 使用参考用于两个目的:简单的 URL 参考和脚注。reStructuredText 区分两者。一个 PEP 可能包含这样的参考

    Abstract
    
        This PEP proposes adding frungible doodads [1] to the core.
        It extends PEP 9876 [2] via the BCA [3] mechanism.
    
    ...
    
    References and Footnotes
    
        [1] http://www.example.org/
    
        [2] PEP 9876, Let's Hope We Never Get Here
            http://peps.python.org/pep-9876/
    
        [3] "Bogus Complexity Addition"
    

    参考 1 是一个简单的 URL 参考。参考 2 是一个包含文本和 URL 的脚注。参考 3 是一个只包含文本的脚注。使用 reStructuredText 重写,此 PEP 可能如下所示

    Abstract
    ========
    
    This PEP proposes adding `frungible doodads`_ to the core.  It
    extends PEP 9876 [#pep9876]_ via the BCA [#]_ mechanism.
    
    ...
    
    References & Footnotes
    ======================
    
    .. _frungible doodads: http://www.example.org/
    
    .. [#pep9876] PEP 9876, Let's Hope We Never Get Here
    
    .. [#] "Bogus Complexity Addition"
    

    如果需要,URL 和脚注可以定义在它们对应的参考附近,这使得它们在源文本中更容易阅读,并使 PEP 更易于修改。“参考和脚注”部分可以使用文档树转换自动生成。来自整个 PEP 的脚注将被收集起来,并显示在标准标题下。如果 URL 参考也应该明确写出来(以引文形式),则可以使用另一个树转换。

    URL 参考可以命名(“frungible doodads”),并且可以从文档中的多个位置引用,而无需额外的定义。转换为 HTML 后,参考将被替换为内联超链接(HTML <a> 标签)。两个脚注自动编号,因此它们将始终保持同步。第一个脚注还包含一个内部引用名称“pep9876”,因此在源文本中更容易看到参考和脚注之间的联系。命名脚注可以引用多次,保持一致的编号。

    “#pep9876”脚注也可以以引文的形式编写

    It extends PEP 9876 [PEP9876]_ ...
    
    .. [PEP9876] PEP 9876, Let's Hope We Never Get Here
    

    脚注是编号的,而引文使用文本作为它们的参考。

  5. 将文档字符串和 PEP 提案分开不是更好吗?

    如果认为没有必要进行 PEP 标记,则可以删除 PEP 标记提案,或者将其改成一个单独的 PEP。如果被接受,PEP 1,PEP 目的和指南,以及 PEP 9,示例 PEP 模板将更新。

    对 Python 中所有结构化纯文本使用的所有用途采用一个一致的标记标准,并在一个地方提出,这似乎是自然的。

  6. 现有的 pep2html.py 脚本将现有的 PEP 格式转换为 HTML。新格式的 PEP 将如何转换为 HTML?

    pep2html.py 的新版本已经完成,该版本集成了 reStructuredText 解析功能。Docutils 项目通过“PEP 阅读器”组件支持 PEP,包括 pep2html.py 中当前的所有功能(自动识别 PEP 和 RFC 引用、电子邮件屏蔽等)。

  7. 谁将把现有的 PEP 转换为 reStructuredText?

    PEP 作者或志愿者可以根据自己的意愿转换现有的 PEP,但没有强制要求这样做。基于 reStructuredText 的 PEP 将与旧的 PEP 标准共存。答案 6 中提到的 pep2html.py 处理旧标准和新标准。

  8. 为什么使用 reStructuredText 作为 README 和其他辅助文件?

    上面答案 4 中关于 PEP 的理由也适用于 README 和其他辅助文件。通过采用标准标记,这些文件可以转换为有吸引力的交叉引用 HTML 并发布到 python.org。其他项目的开发人员也可以利用此功能来完成他们自己的文档。

  9. 与现有标记约定的表面相似性不会造成问题,并导致人们编写无效的标记(并且没有注意到,因为纯文本看起来很自然)?reStructuredText 对“不完全正确”的标记有多宽容?

    会有一些失误,就像从一种编程语言迁移到另一种编程语言时一样。与任何语言一样,熟练程度随着经验的积累而增长。幸运的是,reStructuredText 本身就是一个非常小的语言。

    与任何语法一样,都存在语法错误的可能性。预计用户会在其输入上运行处理系统并检查输出的正确性。

    从严格意义上讲,reStructuredText 解析器非常不宽容(应该如此;“面对模棱两可,拒绝猜测的诱惑” 适用于解析标记和计算机语言)。以下是来自 reStructuredText 简介 的设计目标 3:

    明确性。标记规则不能开放解释。对于任何给定的输入,应该只有一个可能的输出(包括错误输出)。

    虽然不宽容,但解析器同时尝试通过生成有用的诊断输出(“系统消息”)来提供帮助。解析器报告问题,指示其严重程度(从低到高:调试、信息、警告、错误、严重)。用户或客户端软件可以决定报告阈值;他们可以忽略低级问题或导致高级问题立即停止处理。问题在解析期间报告,也包含在输出中,通常在问题来源和解释问题的系统消息之间具有双向链接。

  10. Python 标准库模块中的 docstring 会被转换为 reStructuredText 吗?

    不会。Python 的库参考文档与源代码分开维护。Python 标准库中的 docstring 不应尝试复制库参考文档。Python 标准库中 docstring 的当前策略是,它们应该不超过简洁的提示,简单且无标记(尽管许多确实包含特定于上下文的隐式标记)。

  11. 我想用 Unicode 编写所有字符串。有什么会破坏吗?

    解析器完全支持 Unicode。Docutils 支持任意输入和输出编码。

  12. 为什么社区需要一个新的结构化文本设计?

    现有的结构化文本设计存在缺陷,原因在上面的“基本原理”中给出。reStructuredText 旨在成为一个完整的标记语法,受限于“可读纯文本”媒介。

  13. 现有的文档方法有什么问题?

    什么现有方法?对于 Python docstring,没有官方标准标记格式,更不用说类似于 JavaDoc 的文档方法了。方法论问题比语法(本 PEP 所解决的问题)处于更高的层次。它可能更有争议,也更难以解决,因此有意地不包含在本讨论中。

致谢

部分文字摘自 PEP 216,Docstring 格式,作者 Moshe Zadka。

特别感谢 Python Doc-SIG 的所有过去和现在的成员。


来源:https://github.com/python/peps/blob/main/peps/pep-0287.rst

上次修改时间:2023-09-09 17:39:29 GMT