【问题标题】:One optional argument which does not require positional arguments一个不需要位置参数的可选参数
【发布时间】:2011-10-16 08:21:10
【问题描述】:

我有一个关于 python 的 argparse 的问题:是否可以有一个不需要位置参数的可选参数?

例子:

parser.add_argument('lat', help="latitude")
parser.add_argument('lon', help="longitude")
parser.add_argument('--method', help="calculation method (default: add)", default="add")
parser.add_argument('--list-methods', help="list available methods", action="store_true")

正常的命令行是test.py 47.249 -33.282test.py 47.249 -33.282 --method sub。但是一旦我用test.py --list-methods 调用脚本来列出所有可用的方法,我就会得到error: to few arguments。我如何使用 argparse 来获得这个可选参数(--list-methods)而没有位置参数(lat、lon)?

【问题讨论】:

  • 您可以将 default=None 添加到 lat 和 lon,然后在您的代码中检查 None...
  • 由于您没有设置nargs,看起来很多这些都是必需的。为什么不为可选参数设置 nave nargs='?'

标签: python argparse


【解决方案1】:
  • 为位置参数设置默认值和nargs='?'
  • 在您的代码中手动检查 latitudelongitude 在您未处于 list-methods 模式时是否已设置

    parser = argparse.ArgumentParser()
    
    parser.add_argument('lat', help="latitude",default=None, nargs='?')
    parser.add_argument('lon', help="longitude",default=None, nargs='?')
    parser.add_argument('--method', help="calculation method (default: add)", default="add")
    parser.add_argument('--list-methods', help="list available methods", action="store_true")
    
    args = vars(parser.parse_args())
    
    if not args['list_methods'] and (args['lat'] == None or args['lon'] == None):
        print '%s: error: too few arguments' % sys.argv[0]
        exit(0)
    
    if args['list_methods']:
        print 'list methods here'
    else :
        print 'normal script execution'
    

给出:

$ test.py --list-methods
在此处列出方法

$ test.py 4
test.py:错误:参数太少

test.py 4 5
正常的脚本执行

【讨论】:

    【解决方案2】:

    从 Python 3.3 开始,parse_args 会根据所需的操作集检查其 seen_actions 集,并根据需要发出 the following arguments are required... 错误。之前它检查了剩余的positionals 列表并引发了too few arguments 错误消息。

    所以对于较新的版本,这个 sn-p 应该做你想做的:

    parser = argparse.ArgumentParser()
    lat=parser.add_argument('lat', help="latitude")
    lon=parser.add_argument('lon', help="longitude")
    parser.add_argument('--method', help="calculation method (default: add)", default="add")
    
    class MyAction(argparse._StoreTrueAction):
        def __call__(self, parser, namespace, values, option_string=None):
            setattr(namespace, self.dest, self.const)
            lat.required = False
            lon.required = False
    
    parser.add_argument('--list-methods', help="list available methods", action=MyAction)
    

    通常latlon 是必需的位置,但如果采取--list... 操作,则不再需要这些操作,并且如果缺少它们也不会引发错误消息。


    另一种自定义 argparse 的方法是使用多个解析器。在这种情况下,您可以使用一个解析器来检查 --list-methods 选项,并根据它得到的结果,调用另一个来查找位置。

    parser1 = argparse.ArgumentParser(add_help=False)
    parser1.add_argument('--list-methods', help="list available methods", action='store_true')
    
    parser2 = argparse.ArgumentParser()
    parser2.add_argument('lat', help="latitude")
    parser2.add_argument('lon', help="longitude")
    parser2.add_argument('--method', help="calculation method (default: add)", default="add")
    parser2.add_argument('--list-methods', help="list available methods", action='store_true')
    def foo(argv):
        args,rest = parser1.parse_known_args(argv)
        if not args.list_methods:
            args = parser2.parse_args(argv)
        return args
    

    parser2 响应帮助命令。 parse_known_args 解析它可以解析的内容,并在列表中返回其余部分。 parser2 也可以写成将 rest, args 作为参数。

    【讨论】:

    • 我对流程和副作用有点失望,所以这是我对包装器的建议:``` def positional_discarder(args_to_discard): class DiscardPositionalInput(argparse.Action): def __call__(self , parser, namespace, values, option_string=None): setattr(namespace, self.dest, values) for args_to_discard: arg.required = False return DiscardPositionalInput ``` then parser.add_argument('--list-methods', help="list available methods", action=positional_discarder([lat,long]))
    【解决方案3】:

    您会得到error: to few arguments,因为latlon 参数是必需的。

    In [10]: parser.parse_args('--list-methods'.split())
    ipython: error: too few arguments
    

    但是

    In [11]: parser.parse_args('--list-methods 10 20'.split())
    Out[11]: Namespace(lat='10', list_methods=True, lon='20', method='add')
    

    您应该将 latlon 参数设为可选。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-04
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-16
      相关资源
      最近更新 更多