[英]Unpacking arguments from argparse
我一直在編寫一些命令行python程序並使用argparse
來完成它。 我一直在構建我的代碼,如下所示。
def main(arg1, arg2):
# magic
pass
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('arg1')
parser.add_argument('arg2')
args = parser.parse_args()
main(args.arg1, args.arg2)
不得不召喚arg1
和arg2
3次真的太刺激了。 我明白必須做兩次。
有沒有辦法將parse_args
函數返回的命名空間視為元組? 或者更好的是作為可選args的元組和字典並進行解包?
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('arg1')
parser.add_argument('arg2')
parser.add_argument('--opt-arg', default='default_value')
args, kwargs = parser.magic_method_call_that_would_make_my_life_amazing()
# I get goosebumps just thinking about this
main(*args, **kwargs)
https://docs.python.org/3/library/argparse.html#the-namespace-object
這個類是故意簡單的,只是一個帶有可讀字符串表示的對象子類。 如果您希望使用類似dict的屬性視圖,則可以使用標准Python慣用法,即vars() :
>>>
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
>>> args = parser.parse_args(['--foo', 'BAR'])
>>> vars(args)
{'foo': 'BAR'}
請注意,從optparse
到argparse
一個重大進步或至少更改是位置參數(例如你的)被視為與選項相同。 它們都出現在args
Namespace
對象中。 在optparse
,定位只是解析定義選項的剩余部分。 你可以通過省略你的參數並使用parse_known_args
在argparse
獲得相同的效果:
parser = argparse.ArgumentParser()
args, extras = parser.parse_known_args()
args
現在是一個命名空間,和extras
名單。 然后,您可以將您的功能稱為:
myfoo(*extras, **vars(args))
例如:
In [994]: import argparse
In [995]: def foo(*args, **kwargs):
.....: print(args)
.....: print(kwargs)
.....:
In [996]: parser=argparse.ArgumentParser()
In [997]: parser.add_argument('-f','--foo')
Out[997]: _StoreAction(option_strings=['-f', '--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [998]: args,extras = parser.parse_known_args(['-f','foobar','arg1','arg2'])
In [999]: args
Out[999]: Namespace(foo='foobar')
In [1000]: extras
Out[1000]: ['arg1', 'arg2']
In [1001]: foo(*extras, **vars(args))
('arg1', 'arg2')
{'foo': 'foobar'}
同樣的argparse
段落表明您可以定義自己的Namespace
類。 定義一個行為類似字典(用作**args
)和命名空間的並不難。 所有argparse
要求是它與getattr
和setattr
。
In [1002]: getattr(args,'foo')
Out[1002]: 'foobar'
In [1004]: setattr(args,'bar','ugg')
In [1005]: args
Out[1005]: Namespace(bar='ugg', foo='foobar')
另一個標准的Python功能讓我將vars(args)
作為元組傳遞:
In [1013]: foo(*vars(args).items())
(('foo', 'foobar'), ('bar', 'ugg'))
{}
對於去年1月的類似答案: https : //stackoverflow.com/a/34932478/901925
整齊地將位置參數作為args和可選參數傳遞為從argpase到函數的kwargs
在那里,我提出了如何在解析后將“位置”與“選項”分開的想法。
這是一個自定義命名空間類,在其API中包含一種將自身作為字典返回的方法:
In [1014]: class MyNameSpace(argparse.Namespace):
......: def asdict(self):
......: return vars(self)
......:
In [1015]: args = parser.parse_args(['-f','foobar'], namespace=MyNameSpace())
In [1016]: args
Out[1016]: MyNameSpace(foo='foobar')
In [1017]: foo(**args.asdict())
()
{'foo': 'foobar'}
另一個想法 - 使用多個nargs
(2,'*','+')之一作為位置參數。 然后,在將其傳遞給函數時,只需鍵入一個名稱。
parser.add_argument('pos',nargs='+')
args = ...
args.pos # a list, possibly empty
foo(*args.pos, **vars(args))
這樣做有什么問題
if __name__ == '__main__':
# do argparse stuff as above
main(args)
也就是說,為什么你如此忙於提供main()
位置參數?
說實話,我通常會在模塊的開頭解析a)[for small scripts etc.],它為我提供了一個在所有函數范圍內的變量或者b)[通常]在main()
如果我用你的成語:
def parse_arguments():
parser = argparse.ArgumentParser()
parser.add_argument('arg1')
parser.add_argument('arg2')
args = parser.parse_args()
return args
def main():
args = parse_arguments()
# do stuff with args.arg1 and args.arg2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.