5

根据PEP 257,命令行脚本的文档字符串应该是它的使用信息。

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

所以我的文档字符串看起来像这样:

<工具名称> <版权信息>

用法:<prog name> [options] [args]

一些解释用法的文字...

选项:
  -h, --help 显示此帮助信息并退出
   ...

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

from optparse import OptionParser

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

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

用法:script.py [选项]

选项:
    -h, --help 显示此帮助信息并退出

这可以修改如下:

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

这导致

用法:script.py [选项] [参数]

一些解释用法的文字...

选项:
  -h, --help 显示此帮助信息并退出

但是我怎样才能在这里使用文档字符串呢?将文档字符串作为使用消息传递有两个问题。

  1. 如果文档字符串不以“Usage:”开头,则 optparse 会将“Usage:”附加到文档字符串中
  2. 占位符 '%prog' 必须在文档字符串中使用

结果

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

“Usage:”部分由 IndentedHelpFormatter 引入,可以替换为 OptionParser.__init__() 中的 formatter 参数。

4

3 回答 3

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)
于 2012-04-08T19:02:58.483 回答
4

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

选择 2:解析您自己的文档字符串以删除描述段落。它总是第二段,所以你可以在'\n\n'上拆分。

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

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

于 2009-08-11T12:21:22.527 回答
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)
于 2009-08-11T16:57:39.333 回答