Python-Argparse bedingt erforderlichen Argumente
Habe ich getan, so viel Forschung wie möglich, aber ich habe nicht gefunden, der beste Weg, um sicherzustellen, cmdline Argumente notwendig nur unter bestimmten Bedingungen, in diesem Fall nur, wenn andere Argumente gegeben haben. Hier ist, was ich tun möchte, in einem sehr grundlegenden level:
p = argparse.ArgumentParser(description='...')
p.add_argument('--argument', required=False)
p.add_argument('-a', required=False) # only required if --argument is given
p.add_argument('-b', required=False) # only required if --argument is given
Aus, was ich gesehen habe, andere Leute scheinen einfach nur Ihre eigene Kontrolle am Ende:
if args.argument and (args.a is None or args.b is None):
# raise argparse error here
Gibt es eine Möglichkeit, dies direkt in der argparse-Paket?
- Haben Sie sah
argparse
subparsers? Sie werden Ihnen erlauben, Dinge zu tun, wie$ git commit <commit args only>
oder$ git merge <merge args only>
. - Joel, danke für den Kommentar. Ich habe gesehen, das subparser Aspekt des argparse, aber ich hatte gehofft, dies zu tun, ohne positionale Argumente. Wenn das der einzige Weg, wenn es nicht eine große Sache
- Kann
--a
und--b
gegeben werden, unabhängig?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich habe die Suche nach einer einfachen Antwort auf diese Art von Frage, für einige Zeit. Alles, was Sie tun müssen, ist überprüfen Sie, ob
'--argument'
ist insys.argv
, also im Grunde für dein code-Beispiel könnte man nur tun:Diese Weise
required
erhält entwederTrue
oderFalse
je nachdem, ob der Benutzer als verwendet--argument
. Bereits getestet, scheint zu funktionieren und garantiert, dass-a
und-b
eine unabhängige Verhalten untereinander.-a
ist gegeben aber--argument
ist nicht vorhanden?args = p.parse_args()
Können Sie einen check implementieren, indem Sie eine benutzerdefinierte Aktion für
--argument
, nehmen Sie ein zusätzliches Schlüsselwort-argument, um anzugeben, welche anderen Aktion(en) werden benötigt, wenn--argument
verwendet wird.Die genaue definition von
CondAction
wird davon abhängen, was genau--argument
tun sollte. Aber, zum Beispiel, wenn--argument
ist eine regelmäßige, nehmen Sie-ein-argument-und-speichern-Typ der Aktion, dann nur Erben vonargparse._StoreAction
sollte ausreichend sein.In der Beispiel-parser, speichern wir eine Referenz auf das
--a
option innerhalb der--argument
option, und wenn--argument
ist man auf der Befehl-Linie, setzt es dierequired
Flagge auf--a
zuTrue
. Wenn alle Optionen verarbeitet werden,argparse
prüft, ob die option markiert als erforderlich festgelegt wurde.Action.__call__
gibt einenot implement
Fehler. Aber die Grundidee optimieren, dierequired
Attributx
funktionieren sollte.argparse.Action
, dann gibt es keine Notwendigkeit zum Aufruf des (nicht umgesetzten) parent-Klasse__call__
. Wenn Sie Erben von einem der anderenAction
Unterklasse ist, sollten Sie. (Als Kompromiss, ich bearbeitet die Antwort verlassen der Superklasse Anruf an Ort und Stelle, aber fangen und ignorieren dieNotImplementedError
.)Ihre post-parsing-test ist in Ordnung, vor allem, wenn die Prüfung für Standardwerte mit
is None
zu Ihren Bedürfnissen passt.http://bugs.python.org/issue11588
'Add "necessarily inclusive" groups to argparse'
sieht in Umsetzung von tests wie diese mit dergroups
Mechanismus (eine Verallgemeinerung der mutuall_exclusive_groups).Ich habe geschrieben, eine Reihe von
UsageGroups
implementieren tests wiexor
(sich gegenseitig ausschließende),and
,or
, undnot
. Ich dachte, diejenigen, in denen umfangreiche, aber ich habe nicht in der Lage, um auszudrücken, Ihren Fall in Bezug auf diese Vorgänge. (sieht aus wie ich brauchennand
- und nicht, siehe unten)Dieses Skript verwendet eine benutzerdefinierte
Test
Klasse, dass im wesentlichen realisiert Ihre post-parsing-test.seen_actions
ist eine Liste der Aktionen, die die parse gesehen hat.Beispielausgabe:
usage
- und Fehlermeldungen müssen noch arbeiten. Und es ändert nichts, dass die post-Analyse-test kann nicht.Ihre test löst einen Fehler aus, wenn
(argument & (!a or !b))
. Umgekehrt, was erlaubt ist, ist!(argument & (!a or !b)) = !(argument & !(a and b))
. Durch das hinzufügen einernand
test zu meinemUsageGroup
Klassen, kann ich implementieren Sie Ihren Fall so:Die Nutzung ist (mit
!()
markieren, 'nand' - test):Ich denke, das ist der kürzeste und klarste Weise Ausdrücken, dieses problem mit einer Allgemeinen Zweck-Nutzung-Gruppen.
In meinen tests, Eingänge, analysieren erfolgreich sind:
Diejenigen, die eigentlich Fehler sind:
Bis http://bugs.python.org/issue11588 gelöst ist, würde ich nur verwenden,
nargs
:Diese Weise, wenn jemand versorgt
--arguments
es werden 2 Werte.Vielleicht CLI Ergebnis ist weniger lesbar, aber der code ist viel kleiner. Sie können das Problem beheben, dass mit guten docs/help.
Für Argumente, die ich habe kommen mit einer quick-n-dirty-Lösung wie dieser.
Annahmen: (1) '--help' angezeigt werden sollen, die Hilfe und beschweren sich nicht über das erforderliche argument und (2) wir analysieren
sys.argv
Diese problemlos geändert werden kann, übereinstimmen, eine bestimmte Einstellung.
Für die erforderlichen positionals (der nicht benötigten, wenn z.B. '--help' auf der Kommandozeile) habe ich mit folgendem: [positionals nicht erlauben, für eine
required=...
keyword arg!]im Grunde dreht sich die Anzahl der erforderlichen vorkommen von 'Muster' auf der Kommandozeile aus ein-oder-mehr in die null-oder-mehr-in-Fall '--help' angegeben ist.
Dies ist eigentlich die gleiche wie @Mira 's beantworten, aber ich wollte zeigen, dass es für den Fall, wenn Sie eine option gegeben, dass ein zusätzlicher arg ist erforderlich:
Zum Beispiel, wenn
--option foo
gegeben ist, dann einige Argumente sind auch erforderlich, dass sind nicht erforderlich, wenn--option bar
gegeben:Es ist nicht perfekt - zum Beispiel
proggy --option foo --foo_opt1 bar
ist zweideutig, aber für das, was ich tun musste, ist das ok.