整齐地将位置参数作为args和可选参数传递为从argparse到函数的kwargs

时间:2016-01-21 18:55:08

标签: python argparse args kwargs

我想编写一个Python脚本,通过argparse获取一些必要的位置和一些可选的命令行参数:

  • 让我们调用位置参数abc以及可选参数xyz
  • 在我的Python脚本中,我想将这些args传递给一个函数;具体来说,我希望将abc作为*args传递,将xyz传递给以**kwargs传递,后者保留其姓名。
  • 我想多次使用不同的函数和不同数量的位置和可选参数。是否有一种整洁,灵活和/或pythonic的方式来做到这一点?

以下是一些示例代码:

import argparse

def parse():
    parser = argparse.ArgumentParser()
    parser.add_argument('a', help='1st arg')
    parser.add_argument('b', help='2nd arg')
    parser.add_argument('c', help='3rd arg')
    parser.add_argument('-x', '--x', help='1st kwarg')
    parser.add_argument('-y', '--y', help='2nd kwarg')
    parser.add_argument('-z', '--z', help='3rd kwarg')
    return parser.parse_args()

def func(*args, **kwargs):
    a, b, c = args
    print 'a=', a
    print 'b=', b
    print 'c=', c
    for k, v in kwargs.iteritems():
        print '%s=' % k, v

if __name__ == '__main__':

    all_args = parse()
    ### need to split all_args into args and kwargs here ###
    func(*args, **kwargs)

1 个答案:

答案 0 :(得分:3)

Namespace返回的parse_args将具有与您的每个参数相对应的属性。位置参数和选项之间没有区别,例如:

args
Namespace(a='1',b='one',x='foo', y=...)

正如文件所述,可以访问:

args.a
args.x
etc.

Namespace也可以变成字典:

vars(args)
{'a'='1', 'b'='one', etc.}

您可以将字典作为**kwargs传递给函数。这是标准的Python参数练习。

如果你想传递一些参数*args,你必须自己将这些参数从Namespace或字典中删除。 argparse中的任何内容都不会为您做到这一点。

您可以编写一个类似(未测试)的函数:

def split_args(args):
   vargs = vars(args)
   alist = ['a','b','c']
   args1 = []
   for a in alist:
        v = vargs.pop(a)
        args1.append(v)
   return args1, vars

或者更紧凑一点,将pop放入列表理解中:

In [702]: vargs = dict(a=1,b=3,c=4,x=5,y=3,z=3)
In [703]: [vargs.pop(a) for a in ['a','b','c']]
Out[703]: [1, 3, 4]
In [704]: vargs
Out[704]: {'y': 3, 'x': 5, 'z': 3}

In [705]: def foo(*args,**kwargs):
   .....:     print(args)
   .....:     print(kwargs)
   .....:     
In [706]: vargs = dict(a=1,b=3,c=4,x=5,y=3,z=3)
In [707]: foo(*[vargs.pop(a) for a in ['a','b','c']],**vargs)
(1, 3, 4)
{'x': 5, 'z': 3, 'y': 3}

使用自定义Action类

的进一步想法

parser根据optional属性确定参数是positional还是option_stringsadd_argument返回Action子类,其属性如下:

MyAction(option_strings=[], dest='baz', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

这是positional,因为option_strings是一个空列表。

MyAction(option_strings=['-m', '--mew'], dest='mew', nargs=None,...)

optional,因为该列表不为空。

解析器将输入字符串与option_stringsnargs匹配,然后将值传递给匹配__call__的{​​{1}}方法。此方法定义如下:

Action

这是默认的def __call__(self, parser, namespace, values, option_string=None): setattr(namespace, self.dest, values) 操作。这些值会作为store属性放在Namespace中。

dest参数是触发此调用的字符串,类似于' -m'或{' - mew'或option_string代表None。已定义的操作类型不会使用此操作,但用户定义的Action类可以执行某些操作。

positional

或者您可以使用class MyAction(argparse._StoreAction): def __call__(self, parser, namespace, values, option_string=None): # store option_string along with values in the Namespace setattr(namespace, self.dest, [values,option_string]) 做一些特别的事情,例如

positionals

在解析为:{/ p>之后,可以访问此类 if option_string is None: # append values to a `star_args` attribute # rather than self.dest 之类的操作

positionals

解析器确实维护了这样的列表属性。 args.star_args 返回的extras会暂时存储在parse_known_args的_ {ENRECOGNIZED_ARGS_ATTR'属性。