从argparse整齐地将位置参数作为args传递给可选参数,并将其作为kwargs从argparse传递给函数 [英] Neatly pass positional arguments as args and optional arguments as kwargs from argparse to a function
问题描述
我想编写一个Python脚本,该脚本通过argparse
接受一些必要的位置参数和一些可选的命令行参数:
I would like to write a Python script that takes some necessary positional and some optional command-line arguments via argparse
:
- 让我们调用位置参数
a
,b
,c
和可选参数x
,y
,z
. - 在我的Python脚本中,我想将这些args传递给一个函数;具体来说,我希望
a
,b
,c
作为*args
传递,并且x
,y
,z
作为**kwargs
传递,后者保留其名称./li> - 我想多次使用不同的函数以及不同数量的位置和可选参数来执行此操作.是否有一种简洁,灵活和/或pythonic的方式来做到这一点?
- Let's call the positional args
a
,b
,c
, and the optional argumentsx
,y
,z
. - In my Python script, I would like to pass these args on to a function; specifically, I want
a
,b
,c
to be passed as*args
, andx
,y
,z
to be passed as**kwargs
, the latter retaining their names. - I would like to do this many times with different functions and different numbers of positional and optional arguments. Is there a neat, flexible, and/or pythonic way to do this?
这是一些示例代码:
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)
推荐答案
从parse_args
返回的Namespace
将具有与每个参数对应的属性.位置参数和可选参数之间没有区别,例如:
The Namespace
you get back from parse_args
will have attributes corresponding to each of your arguments. There will be no distinction between the positional arguments and the optionals, e.g.:
args
Namespace(a='1',b='one',x='foo', y=...)
根据文献记载,可以通过以下方式访问:
Which, as is well documented, can be accessed as:
args.a
args.x
etc.
Namespace
也可以变成字典:
vars(args)
{'a'='1', 'b'='one', etc.}
您可以将字典作为**kwargs
传递给函数.这是标准的Python参数练习.
You can pass the dictionary to a function as **kwargs
. That's standard Python argument practice.
如果您想将某些参数作为*args
传递,则必须将这些参数从Namespace
中分离出来或自己编辑字典. argparse
中的任何内容都无法为您做到这一点.
If you want to pass some arguments as *args
you'll have to split those off the Namespace
or dictionary yourself. Nothing in argparse
will do that for you.
您可以编写类似(未测试)的函数:
You could write a function like (not tested):
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
放在列表理解中:
Or more compactly, put the pop
in a list comprehension:
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
通过其option_strings
属性确定参数是optional
还是positional
. add_argument
返回一个Action
子类,该子类将具有以下属性:
Further idea using custom Action class
The parser
determines whether an argument is an optional
vs. positional
by its option_strings
attribute. add_argument
returns an Action
subclass, which will have attributes like:
MyAction(option_strings=[], dest='baz', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
这是一个positional
,因为option_strings
是一个空列表.
This is a positional
because option_strings
is an empty list.
MyAction(option_strings=['-m', '--mew'], dest='mew', nargs=None,...)
是optional
,因为该列表不为空.
is an optional
because that list is not empty.
解析器将输入字符串与option_strings
和nargs
匹配,然后将值传递给匹配的Action
的__call__
方法.此方法的定义如下:
The parser matches input strings with the option_strings
and nargs
, and then passes values to the __call__
method of the matching Action
. This method is defined like:
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, values)
这是默认的store
操作.这些值作为dest
属性放在Namespace
中.
This is the default store
action. The values are put in the Namespace
as the dest
attribute.
option_string
参数是触发此调用的字符串,类似于'-m'或'--mew',或None
表示positional
.定义的动作类型不使用此功能,但是用户定义的Action类可以执行某些操作.
The option_string
parameter is the string that triggered this call, something like '-m' or '--mew', or None
for a positional
. The defined action types don't make use of this, but a user-defined Action class could do something.
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
做一些特殊的事情,例如
Or you could do something special with positionals
, e.g.
if option_string is None:
# append values to a `star_args` attribute
# rather than self.dest
通过这样的操作positionals
可以在解析后访问为:
With an action like this positionals
could be accessed after parsing as:
args.star_args
解析器的确维护这样的list属性. parse_known_args
返回的extras
临时存储在Namespace
的'_UNRECOGNIZED_ARGS_ATTR'属性中.
The parser does maintain a list attribute like this. The extras
that parse_known_args
returns are stored temporarily in the Namespace
in the '_UNRECOGNIZED_ARGS_ATTR' attribute.
这篇关于从argparse整齐地将位置参数作为args传递给可选参数,并将其作为kwargs从argparse传递给函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!