Documenting Python Programs

Home

1 Docstrings

Docstring conventions are described within PEP 257. Their purpose is to provide your users with a brief overview of the object. They should be kept concise enough to be easy to maintain but still be elaborate enough for new users to understand their purpose and how to use the documented object.

In all cases, the docstrings should use the triple-double quote (""") string format. This should be done whether the docstring is multi-lined or not. At a bare minimum, a docstring should be a quick summary of whatever is it you’re describing and should be contained within a single line.

Start with a capital letter, and end with a period.

2 Docstrings Style

From pep258, the docstring is a phrase ending in a period. It prescribes the function or method's effect as a command ("Do this", "Return that"), not as a description; e.g. don't write "Returns the pathname …".

3 Docstrings Types

3.1 Single line summary

'''This program prints out calendar items to start your session.''' This example, while syntatically correct, goes AGAINST PEP 257 guidelines Single liners should simly say "DO THIS, RETURN THAT"

So a better option for the above would be: '''Print out calendar items, with various date calculations.'''

Some more examples: '''Sort according to height, return a list.'''

3.2 Multi-lined


def say_hello(name):
   '''
   Print message, returns nothing

   A simple function that demonstrates docstrings, - oh and also 
   says hello to the name passed to it.
   '''

   print(f"Hello {name}.  Try running help(say_hello) to see the docstring")

3.3 Multi-lined docstring 4 items to contain

Multi-line docstrings have a certain format (by convention only, and described in PEP 257)

They must contain the following 4 items in this order:

  1. A one-line summary
  2. A blank line following the one-line summary
  3. A further elaboration for the doc string that may or may not have blank lines.
  4. Another blank line. (For one-liners there should be NO blank line before or after.)

It appears that some conventions have other standardized formats that include stuff like keyword arguments each on a line by themselves. Here is another example:


def say_hello(name):
   '''A simple function that demonstrates multi-line docstrings. 

   This is the elaboration of this function (or object).  It can be
   for a program itself (i.e. a module) or for a function within the
   module.   This particular case it is for a module that simply
   says hello to the name passed to it'''

   # first line of rest of the function
   print(f"Hello {name}.  Try typing 'help(say_hello)' to see the docstring")

There is a comment after the mandatory blank line after the docstring. the comment isn't mandatory, the blank line is.

Note that for one-liners there should be NO blank line before or after.

All docstrings should have the same max character length as comments (72 characters). Docstrings can be further broken up into three major categories:

  1. Class docstrings
  2. Package and Module Docstrings
  3. Script docstring

3.4 Class docstrings

Created for the class itself, as well as any class methods They are placed immediately after the class or class method, indented by one level.

3.4.1 Class docstrings should contain:

  1. A brief summary of its purpose and behavior
  2. Any public methods, along with a brief description
  3. Any class properties (attributes)
  4. Anything related to the interface for subclassers, if the class is intended to be subclassed

The class constructor parameters should be documented within the __init__ class method docstring. each method should have its own individual docstring

3.4.2 Class Method Docstrings:

  1. A brief description of what the method is and what it’s used for
  2. Any arguments (both required and optional) that are passed including keyword arguments
  3. Label any arguments that are considered optional or have a default value
  4. Any side effects that occur when executing the method
  5. Any exceptions that are raised
  6. Any restrictions on when the method can be called

3.5 Package and Module Docstrings

Package docstrings should be placed at the top of the package’s init.py file. This docstring should list the modules and sub-packages that are exported by the package.

They are similar to Class and Class Method docstrings, but this time for any modules and any functions within the module

3.5.1 Module Docstrings

Module docstrings are placed at the top of the file even before any imports. Module docstrings should include the following:

  1. A brief description of the module and its purpose
  2. A list of any classes, exception, functions, and any other objects exported by the module

3.5.2 Module Function Docstrings

The docstring for a module function should include the same items as a class method:

  1. A brief description of what the method is and what it’s used for
  2. Any arguments (both required and optional) that are passed including keyword arguments
  3. Label any arguments that are considered optional or have a default value
  4. Any side effects that occur when executing the method
  5. Any exceptions that are raised
  6. Any restrictions on when the method can be called

3.6 Script Docstrings

Scripts are considered to be single file executables run from the console. Docstrings for scripts are placed at the top of the file and should be documented well enough for users to be able to have a sufficient understanding of how to use the script. It should be usable for its “usage” message, when the user incorrectly passes in a parameter or uses the -h option.

Some gibberish about argpparsing: If you use argparse, then you can omit parameter-specific documentation, assuming it’s correctly been documented within the help parameter of the argparser.parser.addargument function. It is recommended to use the doc for the description parameter within argparse.ArgumentParser’s constructor.

Finally, any custom or third-party imports should be listed within the docstrings to allow users to know which packages may be required for running the script.

3.7 Another approach that may or may not conflict with the above (test this.)

Python Documentation of Parameters, Returns and Errors We know that at the core of Python Documentation we have the docstring. We also know that we should use it to explain how to use our function, module or class. When talking about functions and methods, it makes sense to explain which parameters we expect and which returns we will give. Furthermore, if the function may generate an error, we want to tell which error may be raised and under which circumstances.

To do all of that, we use the special keywords :param:, :type:, :return:, :rtype:, and :raises:. Specifically, we use them in this way.

:param parametername: description allows you to define a description of the parameter. :type parametername: description allows you to define a description for the type of value expected for the given parameter. :return: description is for specifying a description of the value returned. :rtype: description allows you to explain the type of value returned :raises Exception: description allows you to describe when a specific exception is returned.

4 Docstrings Formats

From realpython :

There are specific docstrings formats that can be used to help docstring parsers and users have a familiar and known format. The formatting used within the examples in this tutorial are NumPy/SciPy-style docstrings.

You can choose the one of your liking, but stay consistent in a project.

Some of the most common formats are the following:

Formatting type Description Formal
    Specification
Google docstrings Google's reommended No
  form of documentation  
reStructured Text Official Python documentation  
  standard. Feature rich, but Yes
  not beginner friendly  
NumPy/SciPy NumPy's combination of  
docstrings reStructured and Google docstrings Yes
Epytext A Python adaption of Epydoc  
  Great for Java developers Yes

Example from NumPy/SciPy

"""Gets and prints the spreadsheet's header columns

Parameters
----------
file_loc : str
    The file location of the spreadsheet
print_cols : bool, optional
    A flag used to print the columns to the console (default is False)

Returns
-------
list
    a list of strings representing the header columns
"""

Here is another example:

class Vehicles(object):
  '''
  The Vehicles object contains lots of vehicles

  Parameters
  ----------
  arg : str
      The arg is used for ...
  *args
      The variable arguments are used for ...
  **kwargs
      The keyword arguments are used for ...

  Attributes
  ----------
  arg : str
      This is where we store arg,
  '''
  def __init__(self, arg, *args, **kwargs):
      self.arg = arg

  def cars(self, distance, destination):
      '''We can't travel distance in vehicles without fuels, so here is the fuels

      Parameters
      ----------
      distance : int
          The amount of distance traveled
      destination : bool
          Should the fuels refilled to cover the distance?

      Raises
      ------
      RuntimeError
          Out of fuel

      Returns
      -------
      cars
          A car mileage
      '''
      pass

Yet a third good example showing best practice to list each argument on a separate line.


def complex(real=0.0, imag=0.0):
    """Form a complex number.

    Keyword arguments:
    real -- the real part (default 0.0)
    imag -- the imaginary part (default 0.0)
    """
    if imag == 0.0 and real == 0.0:
        return complex_zero
    ...

Unless the entire docstring fits on a line, place the closing quotes on a line by themselves. This way, Emacs' fill-paragraph command can be used on it.

5 Example from my cm.py module

cm.py is a module (i.e. no hash-bang line to start) that has as its very first line, the doctring as follows:

'''Print examples using all the possible colours.

Use this to pick out the colour and text highlighting you want to use with your program, then copy the appropriate code to paste into your own print strings.

This program has no imports, and is merely an example of coloured outputs, as well as style outputs.

'''

etc etc.

After importing cm, import cm I ran help(cm) when I got this:


Help on module cm:

NAME
    cm - This utility prints examples using all the possible colours

DESCRIPTION
    Use this to pick out the colour and text highlighting you want
    to use with your program, then copy the appropriate code to
    paste into your own print strings.
    
    This program has no imports, and is merely an example of
    coloured outputs, as well as style outputs.

FILE
    /Users/zintis/bin/python/bin/cm.py

(END)

As you can see, it even gave me the full path of the module, without me having to manually specify it.

6 Best Practices / Rules

These "rules" were taken from ictshore.

6.1 You write code for people to read, not for computers.

6.2 Documenting means adding an explanation to your code.

6.3 Code and documentation must reside in the same place.

6.4 Docstrings are for people using your component. Components are for people editing its code base.

Never use a comment when you should use a docstring, never use a docstring when you should use a comment.

6.5 What to leave out of docstrings

Ideally, a docstring should explain what the function, class or module does. It should not explain the way it works inside, but only how you can use the component from the outside. By reading the docstring, you should know how to use the function, class or module it explains. You shouldn’t worry about ' how it works, only about how you can use it.

A comment should never span multiple lines, and it should explain what the code is doing. Comments are your best friend when it comes to documenting the code inside a function.

7 reStructured Text?

Who said your docstrings should contain boring text? They shouldn’t! In fact, you should write them with the reStructured Text (RST) syntax.

RST is a way of writing text document so that they remain readable as text document, but can be parsed into something more graphical as well.

RST is a syntax for plain-text document that adds embellishments when processed with an RST reader. However, you can still read it as plain text.

RST Syntax for people in a hurry Python documentation heavily rely on RST. This doesn’t mean you have to know it all, but knowing some is certainly good. This is what you will be adding all the time in your docstrings.

text makes the text bold. text makes the text italic. You can combine the two above in text, which results in bold and italic. You can also add an underline to your text with =, * and - to make the text look like a title. Optionally, you can add also the same line above the text, the effect won’t change. However, the underline should be as long as the text, or even longer.

Heading ===== Subheading ** Even smaller heading


You can also use the special syntax :func: to reference a function (or method), :class: to reference a class and :mod: to reference a module. After that, write the component name between special quotes as in the example below. When a RST parser will build the text, it will create a link to the component you are referencing. Much better than writing just the component name.

:mod:`mymodule` :class:`mymodule.MyClass` :func:`mymodule.MyClass.mymethod` :func:`mymodule.myfunction` Sometimes, things can look really ugly if you have a long dependency tree like mysupermodule.mysubmodule.MyClass.mymethod. Showing all of that is cumbersome, for no reason. We can avoid that with ~: adding this symbol at the beginning of the reference will show only the last item. For example, :func:`~mysupermodule.mysubmodule.MyClass.mymethod` will render simply as mymethod. Of course, the link will still point to the correct position.

8 Review (from pep-0257)

Multi-line docstrings consist of:

  • summary line just like a one-line docstring, followed by
  • a blank line, followed by
  • a more elaborate description.

The summary line may be used by automatic indexing tools; it is important that it fits on one line and is separated from the rest of the docstring by a blank line. The summary line may be on the same line as the opening quotes or on the next line. The entire docstring is indented the same as the quotes at its first line (see example below).

Insert a blank line after all docstrings (one-line & multi-line) that document a class – generally speaking, the class's methods are separated from each other by a single blank line, and the docstring needs to be offset from the first method by a blank line.

The docstring of a script (a stand-alone program) should be usable as its "usage" message, printed when the script is invoked with incorrect or missing arguments (or perhaps with a "-h" option, for "help"). Such a docstring should document the script's function and command line syntax, environment variables, and files. Usage messages can be fairly elaborate (several screens full) and should be sufficient for a new user to use the command properly, as well as a complete quick reference to all options and arguments for the sophisticated user.

The docstring for a module should generally list the classes, exceptions and functions (and any other objects) that are exported by the module, with a one-line summary of each. (These summaries generally give less detail than the summary line in the object's docstring.) The docstring for a package (i.e., the docstring of the package's init.py module) should also list the modules and subpackages exported by the package.

The docstring for a function or method should summarize its behavior and document its arguments, return value(s), side effects, exceptions raised, and restrictions on when it can be called (all if applicable). Optional arguments should be indicated. It should be documented whether keyword arguments are part of the interface.

The docstring for a class should summarize its behavior and list the public methods and instance variables. If the class is intended to be subclassed, and has an additional interface for subclasses, this interface should be listed separately (in the docstring). The class constructor should be documented in the docstring for its init method. Individual methods should be documented by their own docstring.

If a class subclasses another class and its behavior is mostly inherited from that class, its docstring should mention this and summarize the differences. Use the verb "override" to indicate that a subclass method replaces a superclass method and does not call the superclass method; use the verb "extend" to indicate that a subclass method calls the superclass method (in addition to its own behavior).

Do not use the Emacs convention of mentioning the arguments of functions or methods in upper case in running text. Python is case sensitive and the argument names can be used for keyword arguments, so the docstring should document the correct argument names. It is best to list each argument on a separate line.

9 Final example from readthedeocs.io:

oding: utf-8 -*- """Example Google style docstrings.

This module demonstrates documentation as specified by the `Google Python Style Guide`_. Docstrings may extend over multiple lines. Sections are created with a section header and a colon followed by a block of indented text.

Example: Examples can be given using either the ``Example`` or ``Examples`` sections. Sections support any reStructuredText formatting, including literal blocks::

$ python examplegoogle.py

Section breaks are created by resuming unindented text. Section breaks are also implicitly created anytime a new section starts.

Attributes: modulelevelvariable1 (int): Module level variables may be documented in either the ``Attributes`` section of the module docstring, or in an inline docstring immediately following the variable.

Either form is acceptable, but the two should not be mixed. Choose one convention to document module level variables and be consistent with it.

Todo:

  • For module TODOs
  • You have to also use ``sphinx.ext.todo`` extension

.. _Google Python Style Guide: http://google.github.io/styleguide/pyguide.html

"""

modulelevelvariable1 = 12345

modulelevelvariable2 = 98765 """int: Module level variable documented inline.

The docstring may span multiple lines. The type may optionally be specified on the first line, separated by a colon. """

def functionwithtypesindocstring(param1, param2): """Example function with types documented in the docstring.

`PEP 484`_ type annotations are supported. If attribute, parameter, and return types are annotated according to `PEP 484`_, they do not need to be included in the docstring:

Args: param1 (int): The first parameter. param2 (str): The second parameter.

Returns: bool: The return value. True for success, False otherwise.

.. _PEP 484: https://www.python.org/dev/peps/pep-0484/

"""

def functionwithpep484typeannotations(param1: int, param2: str) -> bool: """Example function with PEP 484 type annotations.

Args: param1: The first parameter. param2: The second parameter.

Returns: The return value. True for success, False otherwise.

"""

def modulelevelfunction(param1, param2=None, *args, **kwargs): """This is an example of a module level function.

Function parameters should be documented in the ``Args`` section. The name of each parameter is required. The type and description of each parameter is optional, but should be included if not obvious.

If \*args or \*\*kwargs are accepted, they should be listed as ``*args`` and ``**kwargs``.

The format for a parameter is::

name (type): description The description may span multiple lines. Following lines should be indented. The "(type)" is optional.

Multiple paragraphs are supported in parameter descriptions.

Args: param1 (int): The first parameter. param2 (:obj:`str`, optional): The second parameter. Defaults to None. Second line of description should be indented. *args: Variable length argument list. **kwargs: Arbitrary keyword arguments.

Returns: bool: True if successful, False otherwise.

The return type is optional and may be specified at the beginning of the ``Returns`` section followed by a colon.

The ``Returns`` section may span multiple lines and paragraphs. Following lines should be indented to match the first line.

The ``Returns`` section supports any reStructuredText formatting, including literal blocks::

{ 'param1': param1, 'param2': param2 }

Raises: AttributeError: The ``Raises`` section is a list of all exceptions that are relevant to the interface. ValueError: If `param2` is equal to `param1`.

""" if param1 == param2: raise ValueError('param1 may not be equal to param2') return True

def examplegenerator(n): """Generators have a ``Yields`` section instead of a ``Returns`` section.

Args: n (int): The upper limit of the range to generate, from 0 to `n` - 1.

Yields: int: The next number in the range of 0 to `n` - 1.

Examples: Examples should be written in doctest format, and should illustrate how to use the function.

>>> print([i for i in examplegenerator(4)]) [0, 1, 2, 3]

""" for i in range(n): yield i

class ExampleError(Exception): """Exceptions are documented in the same way as classes.

The init method may be documented in either the class level docstring, or as a docstring on the init method itself.

Either form is acceptable, but the two should not be mixed. Choose one convention to document the init method and be consistent with it.

Note: Do not include the `self` parameter in the ``Args`` section.

Args: msg (str): Human readable string describing the exception. code (:obj:`int`, optional): Error code.

Attributes: msg (str): Human readable string describing the exception. code (int): Exception error code.

"""

def _init_(self, msg, code): self.msg = msg self.code = code

class ExampleClass(object): """The summary line for a class docstring should fit on one line.

If the class has public attributes, they may be documented here in an ``Attributes`` section and follow the same formatting as a function's ``Args`` section. Alternatively, attributes may be documented inline with the attribute's declaration (see init method below).

Properties created with the ``@property`` decorator should be documented in the property's getter method.

Attributes: attr1 (str): Description of `attr1`. attr2 (:obj:`int`, optional): Description of `attr2`.

"""

def init_(self, param1, param2, param3): """Example of docstring on the _init method.

The init method may be documented in either the class level docstring, or as a docstring on the init method itself.

Either form is acceptable, but the two should not be mixed. Choose one convention to document the init method and be consistent with it.

Note: Do not include the `self` parameter in the ``Args`` section.

Args: param1 (str): Description of `param1`. param2 (:obj:`int`, optional): Description of `param2`. Multiple lines are supported. param3 (:obj:`list` of :obj:`str`): Description of `param3`.

""" self.attr1 = param1 self.attr2 = param2 self.attr3 = param3 #: Doc comment inline with attribute

#: list of str: Doc comment before attribute, with type specified self.attr4 = ['attr4']

self.attr5 = None """str: Docstring after attribute, with type specified."""

@property def readonlyproperty(self): """str: Properties should be documented in their getter method.""" return 'readonlyproperty'

@property def readwriteproperty(self): """:obj:`list` of :obj:`str`: Properties with both a getter and setter should only be documented in their getter method.

If the setter method contains notable behavior, it should be mentioned here. """ return ['readwriteproperty']

@readwriteproperty.setter def readwriteproperty(self, value): value

def examplemethod(self, param1, param2): """Class methods are similar to regular functions.

Note: Do not include the `self` parameter in the ``Args`` section.

Args: param1: The first parameter. param2: The second parameter.

Returns: True if successful, False otherwise.

""" return True

def _special_(self): """By default special members with docstrings are not included.

Special members are any methods or attributes that start with and end with a double underscore. Any special member with a docstring will be included in the output, if ``napoleonincludespecialwithdoc`` is set to True.

This behavior can be enabled by changing the following setting in Sphinx's conf.py::

napoleonincludespecialwithdoc = True

""" pass

def _specialwithoutdocstring_(self): pass

def _private(self): """By default private members are not included.

Private members are any methods or attributes that start with an underscore and are not special. By default they are not included in the output.

This behavior can be changed such that private members are included by changing the following setting in Sphinx's conf.py::

napoleonincludeprivatewithdoc = True

""" pass

def _privatewithoutdocstring(self): pass

9.1 Home