Python的argh库:在帮助消息中保留docstring格式

时间:2014-05-09 14:39:42

标签: python argparse argh

在我的脚本中搜索更快的方法来解析命令行参数时,我遇到了argh library

我非常喜欢argh的功能但是我遇到了一个阻止我使用它的缺点,这与我在调用-help选项时显示的默认帮助消息有关: 默认情况下,函数的docstring显示在参数列表的顶部。这很好,但初始格式丢失了。例如,请参阅以下示例脚本

import argh

def func(foo=1, bar=True):
    """Sample function.

        Parameters:
            foo: float
                An example argument.
            bar: bool
                Another argument.
    """
    print foo, bar

argh.dispatch_command(func, argv=['-h'])

会导致以下输出

usage: script.py [-h] [-f FOO] [-b]

Sample function. Parameters: foo: float An example argument. bar: bool Another
argument.

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO
  -b, --bar

是否有(简单)方法获得如下输出?

usage: script.py [-h] [-f FOO] [-b]

Sample function.

    Parameters:
        foo: float
            An example argument.
        bar: bool
            Another argument.

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO
  -b, --bar

我宁愿不使用注释来定义参数帮助消息,因为这需要我在每次有变化时都改变函数的文档字符串和帮助文本。

4 个答案:

答案 0 :(得分:6)

我不熟悉argh,但显然它是argparse的包装器。我的猜测是它正在使用你的函数__doc__,并使它成为解析器的description,例如。

parser = argparse.ArgumentParser(description=func.__doc__)

https://docs.python.org/2.7/library/argparse.html#argparse.RawDescriptionHelpFormatter

argparseRawDescriptionHelpFormatter,按原样显示说明。

parser = argparse.ArgumentParser(description=func.__doc__,
    formatter_class=argparse.RawDescriptionHelpFormatter)

所以问题是,有没有办法让argh使用这个格式化程序?

这个argparse脚本会产生您想要的帮助:

import argparse

def func(foo=1, bar=True):
    """Sample function.

        Parameters:
            foo: float
                An example argument.
            bar: bool
                Another argument.
    """
    print foo, bar

parser = argparse.ArgumentParser(prog='script.py',
    description=func.__doc__,
    formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-f', '--foo', type=float)
parser.add_argument('-b', '--bar', action='store_false')
parser.print_help()

argh/dispatching.py

def dispatch_command(function, *args, **kwargs):
    ...
    parser = argparse.ArgumentParser(formatter_class=PARSER_FORMATTER)
    set_default_command(parser, function)
    dispatch(parser, *args, **kwargs)

所以你可以设置:

PARSER_FORMATTER = argparse.RawDescriptionHelpFormatter

或编写自己的函数:

def raw_dispatch_command(function, *args, **kwargs):
    ...
    parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
    set_default_command(parser, function)
    dispatch(parser, *args, **kwargs)

答案 1 :(得分:3)

在@hpaulj的帮助下,我终于设法获得了理想的行为。为了方便这一点,我定义了一个类似于argh.arg的自定义装饰器,目标是不必单独为每个参数写@argh.arg(‘—param’, help=“%(default)s”),而是在我的函数上只使用一个@arg_custom()装饰器:

def arg_custom():
    from argh.constants import ATTR_ARGS
    from argh.assembling import  _get_args_from_signature, _fix_compat_issue29

    def wrapper(func):
        declared_args = getattr(func, ATTR_ARGS, [])
        for a in list(_get_args_from_signature(func)):
             declared_args.insert(0, dict(option_strings=a['option_strings'], help="(default: %(default)s)"))
        setattr(func, ATTR_ARGS, declared_args)
        _fix_compat_issue29(func)
        return func
    return wrapper

这里的关键点是for循环注意所有参数都得到相应的help=“%(default)s”选项。 连同更改argh/constants.py

中的相应行
class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter):
        pass
PARSER_FORMATTER = CustomFormatter

我们现在可以方便地使用

@arg_custom()
def func(foo=1, bar=True):
    """Sample function.

        Parameters:
            foo: float
                An example argument.
            bar: bool
                Another argument.
    """
    print foo, bar

argh.dispatch_command(func)

终于屈服了

usage: script.py [-h] [-f FOO] [-b]

Sample function.

        Parameters:
            foo: float
                An example argument.
            bar: bool
                Another argument.


optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO  (default: 1)
  -b, --bar          (default: True) 

使用-h选项执行脚本时。

答案 2 :(得分:0)

关于在帮助行中获取默认值的问题,此argparse脚本组合了2个格式化程序类

import argparse

def func(foo=1, bar=True):
    ...
    """
    print foo, bar

class MyFormatter(argparse.RawDescriptionHelpFormatter,
    argparse.ArgumentDefaultsHelpFormatter):
    pass

parser = argparse.ArgumentParser(prog='script.py',
    description=func.__doc__,
    formatter_class=MyFormatter)
parser.add_argument('-f', '--foo', type=float, default=1, help='test')
parser.add_argument('-b', '--bar', action='store_false', help='test')
parser.print_help()
制造

usage: script.py [-h] [-f FOO] [-b]

Sample function.
   ...
optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO  test (default: 1)
  -b, --bar          test (default: True)

要获取帮助热线中的默认值,我必须在原始帮助热线中包含一些文字(此处为' test')。

argh中,您可能必须使用注释来为其提供帮助文字。

如果您正在使用注释,请使用$(default)s

为其提供帮助
parser = argparse.ArgumentParser(prog='script.py',
    description=func.__doc__,
    formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-f', '--foo', type=float, default=1, help='default: %(default)s')
parser.add_argument('-b', '--bar', action='store_false', help='default: %(default)s')

答案 3 :(得分:0)

感谢您对Argh图书馆的关注。这里讨论的解决方案将纳入下一个版本(argh≥0.25)。另请参阅issue #64(已修复)。