https://docs.python.org/3/library/argparse.html#the-namespace-object
Questa classe è volutamente semplice, basta una sottoclasse oggetto con una rappresentazione di stringa leggibile. Se si preferisce avere vista dict-simile degli attributi, è possibile utilizzare il linguaggio standard di Python, Vars():
>>>
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
>>> args = parser.parse_args(['--foo', 'BAR'])
>>> vars(args)
{'foo': 'BAR'}
noti che uno dei grandi progressi, o cambiamenti, almeno, da optparse
a argparse
è che gli argomenti posizionali, come i tuoi, sono trattati come opzionali. Entrambi appaiono nell'oggetto args
Namespace
. In optparse
, i posizionali sono solo gli avanzi dall'analisi delle opzioni definite. Si potrebbe ottenere lo stesso effetto in argparse
da Omissione dei vostri argomenti e utilizzando parse_known_args
:
parser = argparse.ArgumentParser()
args, extras = parser.parse_known_args()
args
è ora uno spazio dei nomi, e extras
una lista. Si potrebbe quindi chiamare la funzione come:
myfoo(*extras, **vars(args))
Ad esempio:
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'}
Quello stesso argparse
paragrafo mostra che si può definire il proprio Namespace
classe.Non sarebbe difficile definirne uno che si comporta come un dizionario (da utilizzare come **args
) e come spazio dei nomi. Tutto ciò che richiede argparse
è che funzioni con getattr
e 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')
un'altra caratteristica standard di Python mi permette di passare vars(args)
come una tupla:
In [1013]: foo(*vars(args).items())
(('foo', 'foobar'), ('bar', 'ugg'))
{}
Per una risposta simile da gennaio scorso: https://stackoverflow.com/a/34932478/901925
Neatly pass positional arguments as args and optional arguments as kwargs from argpase to a function
Lì ho dare idee su come per separare i 'posizionali' da 'optionals' dopo l'analisi.
Ecco una classe namespace personalizzato che comprende, nella sua API, un mezzo di per sé che ritorna come un dizionario:
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'}
Un'altra idea - utilizzare uno del molteplice nargs
(2, '*', '+') per l'argomento posizionale. Quindi hai solo un nome da digitare quando lo passi alla tua funzione.
parser.add_argument('pos',nargs='+')
args = ...
args.pos # a list, possibly empty
foo(*args.pos, **vars(args))
Non voglio dover comprimere gli argomenti in una tupla per la mia funzione principale se l'ho importato/richiamato da un altro pacchetto. Mi piace la chiamata al metodo 'parse_arguments'. Lo amo davvero. –