2014-05-09 23 views
5

在我的脚本中搜索更快的方法来解析命令行参数时,我遇到了argh libraryPython的argh库:保留帮助信息中的文档字符串格式

我真的很喜欢argh的功能,但是我遇到了一个阻碍我使用它的缺点,这与如果我调用-help选项时显示的默认帮助消息有关: per默认情况下,函数的文档字符串显示在参数列表的顶部。这很棒,但是最初的格式化会丢失。见,例如,下面的示例脚本

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 

我宁愿不使用注解来定义参数的帮助消息,因为这将需要我改变这两个函数的文档字符串和每个有什么改变时帮助文本。

回答

5

我不熟悉argh,但显然它是​​的包装。我的猜测是,它正在将你的功能__doc__,并使其成为解析器的description,例如,

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

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

​​具有RawDescriptionHelpFormatter显示的描述原样。

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

所以现在的问题是,有没有让argh使用这种格式的一种方式?

这​​脚本生成所需的帮助:

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) 
+0

感谢@hpaulj,这解决了我最初的问题(和immedately导致另一个),因为与变化'PARSER_FORMATTER = argparse.ArgumentDefaultsHelpFormatter'到'PARSER_FORMATTER = argparse.RawDescriptionHelpFormatter'我失去了让我的默认值显示的能力。有两种方法可以使用,即保留格式并查看可选参数旁边的默认值吗?另外,如果'ArgumentDefaultsHelpFormatter'是'PARSE_FORMATTER'的默认值,为什么我在示例的帮助信息中看不到'foo = 1'和'bar = True'的值? – nilfisque

+0

在'constants.py','PARSER_FORMATTER = argparse.ArgumentDefaultsHelpFormatter'。此格式化程序在帮助行中包含默认值。所以随着变化,你获得了一个特征,并且松动了另一个。您可能必须构建自己的格式化程序类以获取这两个功能。 – hpaulj

+0

谢谢,遵循[here](https://stackoverflow.com/questions/18462610/argumentparser-epilog-and-description-formatting-in-conjunction-with-argumentdef)的建议,确实可以生成一个继承自这两个格式化程序,并应导致两者的组合。不过,即使使用原始的'PARSER_FORMATTER = argparse.ArgumentDefaultsHelpFormatter',也不会打印任何默认值。 – nilfisque

0

关于在帮助线获得违约的问题,这​​脚本结合了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) 

若要获取默认值帮助行我必须在原始帮助行中包含一些文本(这里是'测试')。

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') 
+0

由于它很长,我提供了一个单独的答案,我已经设法获得所需的行为。 – nilfisque

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) 

-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 (default: 1) 
    -b, --bar   (default: True) 

0

感谢您对Argh图书馆的关注。此处讨论的解决方案将纳入下一版本(argh≥0.25)。另见issue #64(已经修复)。