2013-05-28 13 views
12

sollte Mein Programm die folgenden Optionen enthalten, ordnungsgemäß von argparse analysiert:Python 2.7 argparse: Wie verschachteln optionale mutale exklusive Argumente richtig?

  1. rein optional: [-h, --help] und [-v, --version]
  2. gegenseitig aus: [-f FILE, --file FILE] und [-u URL, --url URL]
  3. optional, wenn --url gewählt wurde: [-V, --verbose]
  4. erforderlich wenn entweder --file oder --url gewählt wurde: [-F, --format FORMAT]

Das würde gewünschte Nutzungsmuster sein:

prog.py [-h] [-v] [-f FILE (-F FORMAT) | -u URL [-V] (-F FORMAT) ] 

mit dem -F Anforderung beide Mitglieder der Gruppe sich gegenseitig ausschließe Anwendung.
Nicht sicher, ob es eher ein positional ist.

So soll es möglich sein, zu laufen:

prog.py -u "http://foo.bar" -V -F csv 

und den Parser für den Fall, schreit ich die -F vergessen (wie er soll).

Was ich bisher getan haben:

parser = ArgumentParser(decription='foo') 

group = parser.add_mutually_exclusive_group()  
group.add_argument('-f','--file', nargs=1, type=str, help='') 
group.add_argument('-u','--url', nargs=1, type=str, help='')  

parser.add_argument('-V','--verbose', action='store_true', default=False, help='') 
parser.add_argument('-F','--format', nargs=1, type=str, help='') 

Da es ein ‚Vanille-Modus‘ hat ohne Befehlszeilenargumente ausführen können, müssen alle Argumente optional sein.

Wie kann ich Punkte 3. und 4. in meinen Code implementieren?

EDIT:
I -f und -u als subparsers versucht, wie here beschrieben, aber Subbefehle scheinen, wie positionals behandelt werden und der Parser gibt mir eine error: too few arguments, wenn ich es ohne Argumente laufen.

+2

Haben Sie [docopt] (http://docopt.org/) berücksichtigt? Der Nachteil ist, dass Optionswerte mit '-' beginnen können (zB' -fa -F -u '(das Format ist hier "-u")] (https://gist.github.com/zed)/b94e3e9945debe25826d) – jfs

+0

Wird eines von '-f' und' -u' benötigt? Wenn das der Fall ist, stelle ich mir eine Lösung vor, die Unterbefehle oder Positionsargumente enthält. – chepner

+1

@chepner: Nein, sind sie nicht. Ich möchte, dass das Programm auch ohne Argumente und Optionen läuft, so dass es einen Benutzerdialog oder sogar eine GUI startet. – ferkulat

Antwort

5

Verwendung von nargs = 2 und Tupel metavar annähert Ihr Ziel

parser = argparse.ArgumentParser(prog='PROG') 
group = parser.add_mutually_exclusive_group() 
group.add_argument('-f','--file', nargs=2, metavar=('FILE','FORMAT')) 
group.add_argument('-u','--url', nargs=2, metavar=('URL','FORMAT')) 
parser.add_argument('-V','--verbose', action='store_true',help='optional with url') 

, die produziert:

entlang
usage: PROG [-h] [-f FILE FORMAT | -u URL FORMAT] [-V] 

optional arguments: 
    -h, --help   show this help message and exit 
    -f FILE FORMAT, --file FILE FORMAT 
    -u URL FORMAT, --url URL FORMAT 
    -V, --verbose   optional with url 

Dies erfordert das Format mit Dateiname oder URL benötigt es einfach nicht die -F. Wie andere erwähnt -V kann in der -f Fall ignoriert werden.


I tried -f and -u as subparsers, as described here, but subcommands seem to be treated like positionals and the parser gives me an error: too few arguments if i run it without arguments.

In der neuesten Version (en) Subbefehle nicht mehr als erforderlich positionals behandelt. Dies war, wie ich es am besten beurteilen kann, ein Nebeneffekt der Änderung der Fehlermeldung, um informativer zu sein. Statt _parse_known_args a tun:

if positionals: 
     self.error(_('too few arguments')) 

scannt _actions zu sehen, welche erforderlich sind, und dann listet sie namentlich in der Fehlermeldung. Dies wird in http://bugs.python.org/issue9253 diskutiert. Ich weiß, dass diese Änderung in Entwicklung ist (3.4) und möglicherweise auch in 3.3.


2

Diese Punkte können in optparse mit einer callback Methode erzwungen werden, wenn eine bestimmte Option vorhanden ist.

In argparse sind diese jedoch nicht verfügbar.

Sie können eine subparser für die url und die file Unteroption hinzufügen und diese separat analysieren. aus der Hilfe:

Note that the object returned by parse_args() will only contain attributes for the main parser and the subparser that was selected by the command line (and not any other subparsers). So in the example above, when the a command is specified, only the foo and bar attributes are present, and when the b command is specified, only the foo and baz attributes are present.

Aber ich würde die Verwendung nur richtig dokumentieren, und nur die Argumente ignorieren, die nicht anwendbar sind.

z.B.lassen sich diese beiden Befehlszeilen verhalten sich genau das gleiche:

prog.py -f FILE -V 
prog.py -f FILE 
+1

' argparse 'hat integrierte Unterstützung für Optionen mit einer variablen Anzahl von Argumenten, sowie benutzerdefinierte Aktionen, um das Argument (oder die Argumente) einer gegebenen Option zu verarbeiten. Ich stimme jedoch zu, dass es in diesem Fall am einfachsten ist, "-V" zuzulassen und es zu ignorieren, wenn "-f" verwendet wird. – chepner

+0

'optparse' ist veraltet und' argparse' ist sein Ersatz. Siehe: https://docs.python.org/3/library/argparse.html#upgrading-optparse-code –

Verwandte Themen