Sphinx Autodoc ist nicht automatisch genug


149

Ich versuche, mit Sphinx ein Projekt mit mehr als 5.000 Zeilen in Python zu dokumentieren. Es hat ungefähr 7 Basismodule. Soweit ich weiß, muss ich für die Verwendung von Autodoc für jede Datei in meinem Projekt folgenden Code schreiben:

.. automodule:: mods.set.tests
    :members:
    :show-inheritance:

Das ist viel zu langweilig, weil ich viele Dateien habe. Es wäre viel einfacher, wenn ich nur angeben könnte, dass das 'Mods'-Paket dokumentiert werden soll. Sphinx könnte dann rekursiv das Paket durchgehen und eine Seite für jedes Submodul erstellen.

Gibt es eine solche Funktion? Wenn nicht, könnte ich ein Skript schreiben, um alle ersten Dateien zu erstellen, aber das würde viel Zeit in Anspruch nehmen.


Was ist falsch daran, ein kleines Skript zu schreiben, das "os.walk" verwendet und all dies schreibt? Übrigens, ich habe ein Projekt mit mehr als 40.000 Leitungen und weiß nicht, wovon Sie sprechen. Wie viele Dateien sind betroffen? Wie schwierig kann es sein, lszu einer Datei zu routen und diese zu bearbeiten?
S.Lott

124
Niemand sagte, es sei schwer. OP sagte, es sei langweilig , was es ist. Angesichts der Tatsache, dass andere Dokumentensysteme dies können, ist dies nicht unangemessen.
Gregg Lind

Verwenden Sie einfach pdoc .
K3 --- rnc

Antworten:


143

Sie können dieses Skript überprüfen , das ich erstellt habe. Ich denke, es kann dir helfen.

Dieses Skript analysiert einen Verzeichnisbaum, der nach Python-Modulen und -Paketen sucht, und erstellt ReST-Dateien entsprechend, um eine Codedokumentation mit Sphinx zu erstellen. Außerdem wird ein Modulindex erstellt.

AKTUALISIEREN

Dieses Skript ist jetzt Teil von Sphinx 1.1 als Apidoc .


Wohin sollen Sie die Dateien ausgeben? Ich habe versucht, sie in den Standardordner _build von Sphinx auszugeben, aber beim Ausführen werden sphinx-build -b html . ./_buildsie nicht erfasst .
Cerin

Sie sollten sie in die source directory(. In Ihrem Fall) setzen. Im Verzeichnis _build werden die HTML-Dateien erstellt. Überprüfen Sie für weitere Informationen: sphinx.pocoo.org/tutorial.html#running-the-build
Etienne

1
@Erienne: fantastisches Drehbuch! genau das, wonach ich gesucht habe. Ich wünschte, es würde Überschriften für einzelne Klassen generieren (der reguläre Sphinx-Look ist für Klassen nicht gut. Sie gehen in größeren Modulen verloren)
jbenet

1
Sogar Sphinx-Apidoc ist ziemlich rudimentär. Für ein Paket mit einem oder zwei Modulen funktioniert es in Ordnung, aber wir haben Module, die tief verschachtelt sind, und sphinx-apidoc erzeugt eine ziemlich unüberschaubare Ausgabe.
Slacy

4
Selbstantworten: Hinzufügen .. include:: modules.rstzu Ihremindex.rst
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

39

Ich weiß nicht, ob Sphinx autosummaryzum Zeitpunkt der ursprünglichen Frage eine Erweiterung hatte, aber im Moment ist es durchaus möglich, eine solche automatische Generierung ohne Verwendung eines sphinx-apidocähnlichen Skripts einzurichten . Unten finden Sie Einstellungen, die für eines meiner Projekte funktionieren.

  1. Aktivieren Sie die autosummaryErweiterung (sowie autodoc) in der conf.pyDatei und setzen Sie die autosummary_generateOption auf True. Dies kann ausreichen, wenn Sie keine benutzerdefinierten *.rstVorlagen verwenden. Fügen Sie andernfalls Ihr Vorlagenverzeichnis hinzu, um die Liste auszuschließen, oder autosummaryversuchen Sie, sie als Eingabedateien zu behandeln (was ein Fehler zu sein scheint).

    extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autosummary']
    autosummary_generate = True
    templates_path = [ '_templates' ]
    exclude_patterns = ['_build', '_templates']
  2. Verwendung autosummary::im Inhaltsverzeichnisbaum in Ihrer index.rstDatei. In diesem Beispiel Dokumentation für Module project.module1und project.module2wird automatisch generiert und in platziert _autosummaryVerzeichnis.

    PROJECT
    =======
    
    .. toctree::
    
    .. autosummary::
       :toctree: _autosummary
    
       project.module1
       project.module2
  3. Standardmäßig autosummarywerden nur sehr kurze Zusammenfassungen für Module und ihre Funktionen generiert. Um dies zu ändern, können Sie eine benutzerdefinierte Vorlagendatei einfügen_templates/autosummary/module.rst (die mit Jinja2 analysiert wird ):

    {{ fullname }}
    {{ underline }}
    
    .. automodule:: {{ fullname }}
        :members:

Zusammenfassend ist es nicht erforderlich, das _autosummaryVerzeichnis unter Versionskontrolle zu halten . Sie können es auch beliebig benennen und an einer beliebigen Stelle im Quellbaum platzieren (das Platzieren unten _buildfunktioniert jedoch nicht).


4
Das war eine große Hilfe. Gibt es in Punkt 2, in dem Sie "project.module1" und "project.module2" haben, eine Möglichkeit, diese Liste für jedes Modul in einem bestimmten Paket automatisch zu generieren? Um einfach "Projekt" zu setzen und "Modul1" und "Modul2" herausschnüffeln zu lassen?
Brown

Ziemlich überrascht, dass ich nirgendwo eine Antwort darauf finden kann. Hast du es jemals herausgefunden? @Brown?
Alisdair Robertson

3
@AlisdairRobertson Nein, aber die bereitgestellte Autosummary-Lösung war mehr als ausreichend für meine Bedürfnisse. Das einzige andere, woran ich dachte, war, ein Skript zu schreiben, um die Datei index.rst zu generieren und die Modulnamen automatisch zu erkennen. In der Praxis ändert sich die Liste der Module jedoch nicht so oft, sodass es nicht so unvernünftig ist, nur gelegentlich eine Datei zu bearbeiten. Ich bin sicher, ich habe bereits viel mehr Zeit damit verbracht, nach einer Lösung zu suchen, als nur diese eine Datei zu bearbeiten!
Brown

12

In jedem Paket kann die __init__.pyDatei .. automodule:: package.moduleKomponenten für jeden Teil des Pakets enthalten.

Dann können Sie .. automodule:: packageund es macht meistens, was Sie wollen.


setze ich diesen String nur in dreifache Anführungszeichen in init .py?
Cory Walker

5
@Cory Walker: Es ist keine "eine" Zeichenfolge. Sie können und sollten in jede einzelne Datei dreifach zitierte Dokumentzeichenfolgen einfügen. Jeder. Das schließt die __init__.pyDateien in Ihren Paketen ein. Die Dokumentzeichenfolge kann JEDE Sphinx-Dokumentationsanweisung enthalten, auch .. automodule::für Module im Paket.
S.Lott

2
autodocist ein Tippfehler, sollte es sein automodule. aber vielen dank für den hinweis!
Mariotomo

9

Ab Sphinx Version 3.1 (Juni 2020) hat sphinx.ext.autosummary(endlich!) Rekursion.

Sie müssen also keine Modulnamen mehr fest codieren oder sich für die automatische Paketerkennung auf Bibliotheken von Drittanbietern wie Sphinx AutoAPI oder Sphinx AutoPackageSummary verlassen .

Beispiel für ein zu dokumentierendes Python 3.7-Paket ( siehe Code in Github und Ergebnis in ReadTheDocs ):

mytoolbox
|-- mypackage
|   |-- __init__.py
|   |-- foo.py
|   |-- mysubpackage
|       |-- __init__.py
|       |-- bar.py
|-- doc
|   |-- source
|       |--index.rst
|       |--conf.py
|       |-- _templates
|           |-- custom-module-template.rst
|           |-- custom-class-template.rst

conf.py::

import os
import sys
sys.path.insert(0, os.path.abspath('../..'))  # Source code dir relative to this file

extensions = [
    'sphinx.ext.autodoc',  # Core library for html generation from docstrings
    'sphinx.ext.autosummary',  # Create neat summary tables
]
autosummary_generate = True  # Turn on sphinx.ext.autosummary

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

index.rst(Neue :recursive:Option beachten ):

Welcome to My Toolbox
=====================

Some words.

.. autosummary::
   :toctree: _autosummary
   :template: custom-module-template.rst
   :recursive:

   mypackage

Dies reicht aus, um jedes Modul im Paket automatisch zusammenzufassen, auch wenn es tief verschachtelt ist. Für jedes Modul werden dann alle Attribute, Funktionen, Klassen und Ausnahmen in diesem Modul zusammengefasst.

Seltsamerweise sphinx.ext.autosummarygenerieren die Standardvorlagen jedoch keine separaten Dokumentationsseiten für jedes Attribut, jede Funktion, jede Klasse und jede Ausnahme und verknüpfen sie aus den Übersichtstabellen. Es ist möglich, die Vorlagen zu erweitern, um dies zu tun, wie unten gezeigt, aber ich kann nicht verstehen, warum dies nicht das Standardverhalten ist - sicherlich ist es das, was die meisten Leute wollen würden ..? Ich habe es als Feature-Anfrage angesprochen .

Ich musste die Standardvorlagen lokal kopieren und dann hinzufügen:

  • Kopieren site-packages/sphinx/ext/autosummary/templates/autosummary/module.rstnachmytoolbox/doc/source/_templates/custom-module-template.rst
  • Kopieren site-packages/sphinx/ext/autosummary/templates/autosummary/class.rstnachmytoolbox/doc/source/_templates/custom-class-template.rst

Der Haken in custom-module-template.rstist index.rstoben mit der :template:Option. (Löschen Sie diese Zeile, um zu sehen, was mit den Standardvorlagen für Site-Pakete geschieht.)

custom-module-template.rst (zusätzliche Zeilen rechts):

{{ fullname | escape | underline}}

.. automodule:: {{ fullname }}
  
   {% block attributes %}
   {% if attributes %}
   .. rubric:: Module Attributes

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in attributes %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block functions %}
   {% if functions %}
   .. rubric:: {{ _('Functions') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in functions %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block classes %}
   {% if classes %}
   .. rubric:: {{ _('Classes') }}

   .. autosummary::
      :toctree:                                          <-- add this line
      :template: custom-class-template.rst               <-- add this line
   {% for item in classes %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block exceptions %}
   {% if exceptions %}
   .. rubric:: {{ _('Exceptions') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in exceptions %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

{% block modules %}
{% if modules %}
.. rubric:: Modules

.. autosummary::
   :toctree:
   :template: custom-module-template.rst                 <-- add this line
   :recursive:
{% for item in modules %}
   {{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

custom-class-template.rst (zusätzliche Zeilen rechts):

{{ fullname | escape | underline}}

.. currentmodule:: {{ module }}

.. autoclass:: {{ objname }}
   :members:                                    <-- add at least this line
   :show-inheritance:                           <-- plus I want to show inheritance...
   :inherited-members:                          <-- ...and inherited members too

   {% block methods %}
   .. automethod:: __init__

   {% if methods %}
   .. rubric:: {{ _('Methods') }}

   .. autosummary::
   {% for item in methods %}
      ~{{ name }}.{{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block attributes %}
   {% if attributes %}
   .. rubric:: {{ _('Attributes') }}

   .. autosummary::
   {% for item in attributes %}
      ~{{ name }}.{{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.