97

I have a Python script with a docstring. When the parsing of the command-line arguments does not succeed, I want to print the docstring for the user's information.

Is there any way to do this?

Minimal example

#!/usr/bin/env python
"""
Usage: script.py

This describes the script.
"""

import sys


if len(sys.argv) < 2:
    print("<here comes the docstring>")
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
thias
  • 2,290
  • 3
  • 20
  • 20
  • 2
    There are libraries for cmdline argument parsing: argparse (>=2.7) and optparse. http://docs.python.org/dev/library/argparse.html http://docs.python.org/dev/library/optparse.html – codeape Oct 17 '11 at 11:37
  • 12
    I know that but it's not relevant to the question – thias Oct 17 '11 at 11:38
  • 1
    I am one person who sometimes explicitly does *not* want to use argparse for a really simple script, so I'm grateful for those below who answered the question as asked. – SteveWithamDuplicate Jun 24 '21 at 18:04

5 Answers5

115

The docstring is stored in the module's __doc__ global.

print(__doc__)

By the way, this goes for any module: import sys; print(sys.__doc__). Docstrings of functions and classes are also in their __doc__ attribute.

Petr Viktorin
  • 65,510
  • 9
  • 81
  • 81
  • 2
    That definitely works, but there is another way that shows a more native looking module help interface:: `help(module_name)` after you import that module. – danbgray May 03 '16 at 14:33
  • 2
    @danbgray I think what you are getting at is what argparse is used for – james-see Mar 18 '19 at 16:29
  • 1
    WEIRD PYTHON 2 WRINKLE: If you put, e.g. "from \_\_future\_\_ import print_function" before the docstring, *it's not a docstring anymore*. But you can put "from \_\_future\_\_" import... *just after* the docstring, and the "from \_\_future\_\_ imports must occur at the beginning of the file" rule is still satisfied. – SteveWithamDuplicate Jun 24 '21 at 17:59
15

Argument parsing should always be done with argparse.

You can display the __doc__ string by passing it to the description parameter of Argparse:

#!/usr/bin/env python
"""
This describes the script.
"""


if __name__ == '__main__':
    from argparse import ArgumentParser
    parser = ArgumentParser(description=__doc__)
    # Add your arguments here
    parser.add_argument("-f", "--file", dest="myFilenameVariable",
                        required=True,
                        help="write report to FILE", metavar="FILE")
    args = parser.parse_args()
    print(args.myFilenameVariable)

If you call this mysuperscript.py and execute it you get:

$ ./mysuperscript.py --help
usage: mysuperscript.py [-h] -f FILE

This describes the script.

optional arguments:
  -h, --help            show this help message and exit
  -f FILE, --file FILE  write report to FILE
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
14

Here is an alternative that does not hardcode the script's filename, but instead uses sys.argv[0] to print it. Using %(scriptName)s instead of %s improves readability of the code.

#!/usr/bin/env python
"""
Usage: %(scriptName)s

This describes the script.
"""

import sys
if len(sys.argv) < 2:
   print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}
   sys.exit(0)
wint3rschlaefer
  • 198
  • 1
  • 4
  • thanks. I usually have a usage() function that uses sys.argv[0] which is called before printing the docstring. – thias Feb 25 '13 at 09:59
  • @wint3rschlaefer, could you explain how Usage: %(scriptName)s get the script name? What is this mechanism called in python? – olala Jan 24 '16 at 16:40
  • 1
    @wint3rschlaefer Maybe it's worth updating with a python3 version, like `"""Usage: {scriptName}""".format(scriptName = sys.argv[0])` – Cimbali Aug 09 '16 at 10:38
  • 1
    How about using __name_ ? – Otzen Feb 05 '21 at 22:16
1

This will print the __doc__ string when --help is the only argument.

if __name__=='__main__':
 if len(sys.argv)==2 and sys.argv[1]=='--help':
    print(__doc__)

Works for both:

  • ./yourscriptname.py --help
  • python3 yourscriptname.py --help
Semnodime
  • 1,872
  • 1
  • 15
  • 24
Mr CaT
  • 337
  • 3
  • 4
1

An enhancement of @MartinThoma's answer so it prints multi-line docstrings inspired by Python argparse: How to insert newline in the help text?.

Argument parsing should always be done with argparse.

You can display the doc string by passing it to the description parameter of Argparse:

#!/usr/bin/env python 
""" 
This summarizes the script.

Additional descriptive paragraph(s).
"""  # Edited this docstring


if __name__ == '__main__':
    from argparse import ArgumentParser, RawTextHelpFormatter  # Edited this line
    parser = ArgumentParser(description=__doc__
                            formatter_class=RawTextHelpFormatter)  # Added this line
    # Add your arguments here
    parser.add_argument("-f", "--file", dest="myFilenameVariable",
                        required=True,
                        help="write report to FILE", metavar="FILE")
    args = parser.parse_args()
    print(args.myFilenameVariable) 

If you call this mysuperscript.py and execute it you get:

$ ./mysuperscript.py --help
usage: mysuperscript.py [-h] -f FILE

This summarizes the script.

Additional descriptive paragraph(s).

optional arguments:
  -h, --help            show this help message and exit
  -f FILE, --file FILE  write report to FILE

Without the addition of the formatter_class the output would not have the line break in the docstring.

thehale
  • 913
  • 10
  • 18