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

时间:2009-08-11 12:14:49

标签: python optparse

根据PEP 257,命令行脚本的docstring应该是它的用法消息。

  

脚本的文档字符串(a   独立程序)应该可用   作为其“使用”信息,打印时   脚本调用不正确   或缺少参数(或可能与   “-h”选项,用于“帮助”)。这样的   docstring应记录脚本   函数和命令行语法,   环境变量和文件。   用法消息可以相当复杂   (几个屏幕已满)应该是   足以让新用户使用   命令正确,以及一个   完整快速参考所有   的选项和参数   老练的用户。

所以我的docstring看起来像这样:

<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生成“选项”部分和解释命令行语法的“用法”:

from optparse import OptionParser

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

因此,使用“-h”标志调用脚本会打印:

Usage: script.py [options]

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

可以修改如下:

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

导致

Usage: script.py [options] [args]

some text explaining the usage...

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

但是我怎样才能在这里使用docstring?将docstring作为用法消息传递有两个问题。

  1. optparse将“Usage:”附加到docstring,如果它不以“Usage:”开头
  2. 占位符'%prog'必须在docstring
  3. 中使用

    结果

    根据答案,似乎无法重用optparse模块所预期的docstring。所以剩下的选择是手动解析文档字符串并构造OptionParser。 (所以我会接受S.Loot的回答)

    “用法:”部分由IndentedHelpFormatter引入,可以用OptionParser .__ init __()中的formatter参数替换。

3 个答案:

答案 0 :(得分:6)

我写了一个模块docopt来完成你想要的 - 在docstring中编写用法消息并保持DRY。 它还允许避免编写繁琐的OptionParser代码,因为docopt正在生成解析器 基于用法消息。

检查出来:http://github.com/docopt/docopt

"""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 :(得分:4)

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

选择2:解析您自己的文档字符串以去除描述段落。它始终是第2段,因此您可以拆分'\ n \ n'。

usage, description= __doc__.split('\n\n')[:2]

由于optparse生成用法,您可能不希望向其提供用法句子。你的用法版本我错了。如果您坚持向optparse提供使用字符串,我会将其作为练习,让读者了解如何从上面生成的"Usage: "字符串前面删除usage

答案 2 :(得分:1)

我认为我们必须对这个PEP的建议是合理的 - 我认为将__doc__作为总结长期使用的简短描述的模块是可以的。但如果你是完美主义者:

'''<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('\n\n')
docstring[1:2] = [__license__, usage, options]
__doc__ = '\n\n'.join(docstring)