使用Python的optparse模块时如何遵守PEP 257文档字符串?

How to comply to PEP 257 docstrings when using Python's optparse module?

根据PEP257,命令行脚本的docstring应该是其用法消息。

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.

所以我的docstring应该是这样的:

1
2
3
4
5
6
7
8
9
<tool name> <copyright info>

Usage: <prog name> [options] [args]

some text explaining the usage...

Options:
  -h, --help  show this help message and exit
   ...

现在我想使用optparse模块。optparse生成"选项"部分和"用法",解释命令行语法:

1
2
3
4
5
from optparse import OptionParser

if __name__ =="__main__":
    parser = OptionParser()
    (options, args) = parser.parse_args()

所以调用带有"-h"标志打印的脚本:

1
2
3
4
Usage: script.py [options]

Options:
    -h, --help  show this help message and exit

可以修改如下:

1
2
parser = OptionParser(usage="Usage: %prog [options] [args]",
                      description="some text explaining the usage...")

结果是

1
2
3
4
5
6
Usage: script.py [options] [args]

some text explaining the usage...

Options:
  -h, --help  show this help message and exit

但在这里如何使用docstring?将docstring作为用法消息传递有两个问题。

  • optparse如果docstring不是以"usage:"开头,则将"usage:"追加到docstring。
  • 必须在docstring中使用占位符"%prog"
  • 结果

    根据答案,似乎没有办法重用optparse模块预期的docstring。所以剩下的选项是手动解析docstring并构造optionParser。(所以我接受S.Loot的回答)

    "用法:"部分由indentedHelpFormatter引入,它可以替换为OptionParser中的格式化程序参数。


    我编写了一个模块docopt来做你想做的事情——用docstring编写使用消息并保持干燥。它还可以避免编写冗长的OptionParser代码,因为docopt正在生成解析器。基于使用信息。

    请访问:http://github.com/docopt/docopt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    """Naval Fate.

    Usage:
      naval_fate.py ship new <name>...
      naval_fate.py ship [<name>] move <x> <y> [--speed=<kn>]
      naval_fate.py ship shoot <x> <y>
      naval_fate.py mine (set|remove) <x> <y> [--moored|--drifting]
      naval_fate.py -h | --help
      naval_fate.py --version

    Options:
      -h --help     Show this screen.
      --version     Show version.
      --speed=<kn>  Speed in knots [default: 10].
      --moored      Moored (anchored) mine.
      --drifting    Drifting mine.

    """

    from docopt import docopt


    if __name__ == '__main__':
        arguments = docopt(__doc__, version='Naval Fate 2.0')
        print(arguments)

    选择1:复制和粘贴。不干燥,但可行。

    选择2:解析您自己的docstring以去掉描述段落。它总是第二段,所以您可以在'上拆分。

    1
    2
    3
    usage, description= __doc__.split('

    '
    )[:2]

    由于optparse生成了用法,您可能不想向它提供用法语句。你版本的用法我错了。如果你坚持要给optparse提供一个用法字符串,我将把它作为练习留给读者去解决如何从上面生成的usage字符串的前面删除"Usage:"


    我认为我们必须对这一政治公众人物的建议保持合理的态度——我认为把这个模块留给__doc__作为总结长期使用的简短描述是可以的。但如果你是完美主义者:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    '''<tool name>

    The full description and usage can be generated by optparse module.

    Description: ...

    '''


    ...

    # Generate usage and options using optparse.
    usage, options = ...

    # Modify the docstring on the fly.
    docstring = __doc__.split('

    '
    )
    docstring[1:2] = [__license__, usage, options]
    __doc__ = '

    '
    .join(docstring)