Python argparse ignoruje nierozpoznane argumenty

206

Optparse, stara wersja ignoruje wszystkie nierozpoznane argumenty i kontynuuje. W większości sytuacji nie jest to idealne i zostało zmienione w argparse. Ale jest kilka sytuacji, w których chcesz zignorować nierozpoznane argumenty i przeanalizować te, które określiłeś.

Na przykład:

parser = argparse.ArgumentParser()
parser.add_argument('--foo', dest="foo")
parser.parse_args()

$python myscript.py --foo 1 --bar 2
error: unrecognized arguments: --bar

Czy można to jednak zastąpić?

joedborg
źródło
14
Bardzo przydatne, jeśli piszesz opakowanie do innego programu i chcesz przechwycić i zmodyfikować kilka argumentów, ale resztę przekazać!
Alan De Smet
2
Właśnie dlatego skończyłem tutaj @AlanDeSmet! Cieszę się, że nie próbuję zrobić czegoś szalonego :)
dwanderson

Odpowiedzi:

351

Zastąpić

args = parser.parse_args()

z

args, unknown = parser.parse_known_args()

Na przykład,

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo')
args, unknown = parser.parse_known_args(['--foo', 'BAR', 'spam'])
print(args)
# Namespace(foo='BAR')
print(unknown)
# ['spam']
unutbu
źródło
21
+1 - nie wiedziałem, że jest coś takiegoparse_known_args
avasal 10.10.12
7
Ja też nie! Nawet mi tego brakowało w dokumentacji docs.python.org/library/… . Dzięki
joedborg,
1
Pojawiło się to, gdy próbowałem użyć testu nosa z parseargami (odmówiło zgody na użycie argumentów nosa). Powodem było to, że robiłem to, parser.parse_args(None)a nie parser.parse_args([])w moich testach.
Andy Hayden,
3
FWIW, parse_known_argszamiast używać parse_argswłączania ArgumentParserkodu w zakresie if __name__ == 'main':(warunek, który dotyczy Truewszystkich komórek w notesie IPython ...), który znajduję, znacznie pomaga w opracowywaniu i testowaniu kodu, który chcę ostatecznie migrować do wywoływanego skryptu z linii poleceń)
gumption
1
Nie wydaje się, aby działało to z opcjonalnymi argumentami, o których wiadomo, że nie są przekazywane.
Sharud
21

Możesz umieścić pozostałe części w nowym argumencie, parser.add_argument('args', nargs=argparse.REMAINDER)jeśli chcesz ich użyć.

lichenbo
źródło
1
Działa to parse_args()i nie wymaga parse_known_args()(w Pythonie 2.7).
OozeMeister
4
Używanie argparse.REMAINDER wydaje się być obciążony długotrwałymi błędami. Z pewnością nie mogę tego uruchomić. parse_known_args () jest dobrą alternatywą.
Matt
1
Właśnie wpadłem dzisiaj na długotrwały błąd REMAINDER: bugs.python.org/issue17050
Scott Carpenter
7

Właściwie argparse wciąż „ignoruje” _unrecognized_args. Dopóki te „nierozpoznane” argumenty nie używają domyślnego prefiksu , nie usłyszysz żadnych skarg od parsera.

Używając konfiguracji @ anutbu, ale ze standardem parse.parse_args(), gdybyśmy mieli uruchomić nasz program z następującymi argumentami.

$ program --foo BAR a b +cd e

Będziemy mieć tę kolekcję danych o przestrzeni nazw do pracy.

Namespace(_unrecognized_args=['a', 'b', '+cd', 'e'], foo='BAR')

Gdybyśmy chcieli -zignorować domyślny prefiks , moglibyśmy zmienić ArgumentParser i zdecydować, że +zamiast tego użyjemy argumentu „nasze” rozpoznane.

parser = argparse.ArgumentParser(prefix_chars='+')
parser.add_argument('+cd')

To samo polecenie wygeneruje

Namespace(_unrecognized_args=['--foo', 'BAR', 'a', 'b'], cd='e')

Włóż to do fajki i zapal go =)

nJoy!

nikiel
źródło