2017-02-22 4 views
0

Ich habe eine argparser, mit zwei Teilmengen von Argumenten, Eingaben und Parametern. Mein Befehl sieht so etwas wieist es möglich, eine Reihe von argparse-Argumenten zu bezeichnen, ohne Subparser zu verwenden?

program -input1 <input1> -input2 <input2> -p1 <param1> -p2 <param2> 

ich

args = parser.parse_args() 
params = vars(args.params) 

statt

params = {"p1": args.p1, "p2": args.p2, etc...} 

Gibt es eine elegante Art und Weise, wie etwas zu tun lieben würde:

parser.add_argument("-p1", dest='p1', part_of=params) 

Subparsers scheint nicht l Sie sind dafür gemacht. Oder sind Sie?

Argparse hat argument groups, aber sie scheinen nur für den Hilfetext.

Danke!

+1

Ich bin nicht klar auf was Sie versuchen zu tun. Meinst du, '-p1' und' -p2' können nur mit/als Unterstrukturen/"Unteroptionen" von -input2' auftreten? – jwodder

+1

Argumentgruppen sind meistens nützlich für sich gegenseitig ausschließende Optionen. Was ist die Natur deiner Gruppen? Z.B. Könnten Sie einfach 'dest' als Hilfe für die Gruppierung von Parametern hinzufügen? – 9000

+0

Wie gehst du Prefixing dest? @ 9000 –

Antwort

0

Das klingt wie eine Variation der - wie akzeptiere ich willkürlich 'Schlüssel = Wert' Paare? Es wurde im Laufe der Jahre auf verschiedene Arten mit verschiedenen Antworten gefragt.

In einer kürzlich ein:

Parsing "python foo.py -DVAR1=9 -DVAR2=Off" with argparse

meine Lösung war -DVAR1=9 in ('VAR1',9) und fügen Sie, dass an den D Attribut zu teilen. Das verwendet eine benutzerdefinierte type.

Using variable arg names with argparse - dies verarbeitet die sys.argv, bevor es an den Parser übergeben.

python argparse store --foo=bar as args.key='foo', args.value='bar'

schlägt eine benutzerdefinierte Action Klasse.

Ich denke, wir haben auch eine benutzerdefinierte Namespace Klasse vorgeschlagen. Die integrierten Mechanismen zum Gruppieren von Werten sind nargs und append Aktion. Zusammen können Sie Attribute erhalten, die Listen von Listen sind.

JSON-Strings können auch zur Eingabe komplexer Datenstrukturen verwendet werden.


class MyAction(argparse._StoreAction): 
    def __call__(self, parser, namespace, values, option_string=None): 
     print('storing', option_string) 
     arg = getattr(namespace, self.dest) 
     if arg is None: 
      arg = {} 
     arg[option_string] = values 
     setattr(namespace, self.dest, arg) 

In [135]: p=argparse.ArgumentParser() 
In [136]: p.add_argument('--p1',action=MyAction,dest='p'); 
In [137]: p.add_argument('--p2',action=MyAction,dest='p'); 
In [138]: p.parse_args('--p1 one --p2 two'.split()) 
storing --p1 
storing --p2 
Out[138]: Namespace(p={'--p2': 'two', '--p1': 'one'}) 
In [139]: _.p 
Out[139]: {'--p1': 'one', '--p2': 'two'} 

Offensichtlich könnte dies auf verschiedene Weise verfeinert werden - die Schlüssel Trimmen ‚p1‘ oder sogar ‚1‘, um eine Liste zu speichern, oder verschachtelter Namespace oder andere benutzerdefinierte Struktur usw.

Dieser Ansatz erfordert weiterhin, dass Sie für jede '-pn'-Variante einen add_argument definieren.

Eine Alternative ist argparse einfach zu halten, produzieren einen Namespace wie:

In [141]: argparse.Namespace(p1='one', p2='two', input1=1, input2=3) 
Out[141]: Namespace(input1=1, input2=3, p1='one', p2='two') 

und dann anschließend Ihre eigene Gruppierung tun.

In [142]: args=argparse.Namespace(p1='one', p2='two', input1=1, input2=3) 
In [143]: {key:getattr(args,key) for key in ['p1','p2']} 
Out[143]: {'p1': 'one', 'p2': 'two'} 
+0

können Sie es besser machen? Meine Frage erneut lesen - was wieder relevant geworden ist - ich denke, diese Funktionalität sollte von Python bereitgestellt werden. Ich weiß nicht viel über die Governance von Python, aber ich würde gerne etwas dazu beitragen. In meinen Augen würde dies die [Argumentgruppen] aufbauen (https://docs.python.org/3.6/library/argparse.html#argument-groups), die bereits dort sind, aber nur für den Hilfetext verwendet werden. –

+0

Sie sind herzlich eingeladen, nach 'argparse' Problemen auf' http: // bugs.python.org/'zu suchen. Studieren Sie einige von denen, sowohl offene als auch geschlossene, um zu sehen, was bei einer Veränderung eine Rolle spielt. Es gibt zwei Herausforderungen 1), die den Fall, dass dies ein dringendes und allgemeines Problem ist, und 2) das Schreiben eines kompletten Patches (mit Tests und Dokumentation). – hpaulj

Verwandte Themen