簡體   English   中英

從argparse解包參數

[英]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)

不得不召喚arg1arg2 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'}

請注意,從optparseargparse一個重大進步或至少更改是位置參數(例如你的)被視為與選項相同。 它們都出現在args Namespace對象中。 optparse ,定位只是解析定義選項的剩余部分。 你可以通過省略你的參數並使用parse_known_argsargparse獲得相同的效果:

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要求是它與getattrsetattr

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

你可以在這里看到類似的問題。

編輯 :尋找一種不使用內部方法的方法,我發現這個討論建議使用vars() 這非常有效:

import argparse

def main(arg1, arg2):
    print arg1, arg2

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('arg1')
    parser.add_argument('arg2')

    args = parser.parse_args()
    main(**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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM