Argumentować opcjonalne argumenty pozycyjne?

651

Mam skrypt, którego należy używać w następujący sposób: usage: installer.py dir [-h] [-v]

dir jest argumentem pozycyjnym zdefiniowanym w następujący sposób:

parser.add_argument('dir', default=os.getcwd())

Chcę, diraby był opcjonalny: jeśli nie jest określony, powinien po prostu być cwd.

Niestety, gdy nie podam dirargumentu, rozumiem Error: Too few arguments.

Waldo Bronchart
źródło

Odpowiedzi:

825

Użyj nargs='?'(lub nargs='*' jeśli będziesz potrzebować więcej niż jednego katalogu)

parser.add_argument('dir', nargs='?', default=os.getcwd())

rozszerzony przykład:

>>> import os, argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-v', action='store_true')
_StoreTrueAction(option_strings=['-v'], dest='v', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('dir', nargs='?', default=os.getcwd())
_StoreAction(option_strings=[], dest='dir', nargs='?', const=None, default='/home/vinay', type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('somedir -v'.split())
Namespace(dir='somedir', v=True)
>>> parser.parse_args('-v'.split())
Namespace(dir='/home/vinay', v=True)
>>> parser.parse_args(''.split())
Namespace(dir='/home/vinay', v=False)
>>> parser.parse_args(['somedir'])
Namespace(dir='somedir', v=False)
>>> parser.parse_args('somedir -h -v'.split())
usage: [-h] [-v] [dir]

positional arguments:
  dir

optional arguments:
  -h, --help  show this help message and exit
  -v
Vinay Sajip
źródło
14
Czy ?i *oznaczają to samo, co oznaczają w wyrażeniach regularnych (tj. ?Wymaga 0 lub 1 i *wymaga 0 lub więcej)? Jeśli tak, czy również +działa?
Dolan Antenucci
37
@dolan: Tak, też +działa. Szczegóły znajdują się w docs.python.org/2/library/argparse.html#nargs .
Vinay Sajip
2
czy jest jakiś sposób, żeby reż pojawił się w opcjonalnych argumentach? lub wydaje się, że argumenty pozycyjne powinny mieć poprzedzający „opcjonalny” kwalifikator. czy można zarejestrować (w zakresie pomocy) jako taką?
scagnetti
6
@ant Z powyższego widać, że katalog jest opcjonalny (wskazuje to w nawiasach kwadratowych w wynikach argparse).
Vinay Sajip
1
Tx! Uzyskaj dostęp do katalogu z options.dir, nie args.dir, tak jak próbowałem!
ptim
69

Jako rozszerzenie odpowiedzi @VinaySajip. Są dodatkowe nargswarte wspomnienia .

  1. parser.add_argument('dir', nargs=1, default=os.getcwd())

N (liczba całkowita). N argumentów z wiersza poleceń zostanie zebranych razem na liście

  1. parser.add_argument('dir', nargs='*', default=os.getcwd())

„*”. Wszystkie obecne argumenty wiersza poleceń są gromadzone na liście. Zauważ , że generalnie nie ma większego sensu mieć więcej niż jeden argument pozycyjny z nargs='*', ale nargs='*'możliwe jest wiele opcjonalnych argumentów z .

  1. parser.add_argument('dir', nargs='+', default=os.getcwd())

„+”. Podobnie jak „*” wszystkie obecne argumenty wiersza poleceń są gromadzone na liście. Ponadto zostanie wygenerowany komunikat o błędzie, jeśli nie będzie co najmniej jednego argumentu wiersza polecenia.

  1. parser.add_argument('dir', nargs=argparse.REMAINDER, default=os.getcwd())

argparse.REMAINDER. Wszystkie pozostałe argumenty wiersza poleceń są zebrane w listę. Jest to zwykle przydatne w przypadku narzędzi wiersza polecenia, które są wysyłane do innych narzędzi wiersza polecenia

Jeśli nargsnie podano argumentu słowa kluczowego, liczba wykorzystanych argumentów jest określona przez działanie. Ogólnie oznacza to, że zużyty zostanie jeden argument wiersza poleceń i zostanie wygenerowany pojedynczy element (nie lista).

Edytuj (skopiowane z komentarza @Acumenus) nargs='?' Dokumenty mówią: „?”. Jeden argument zostanie wykorzystany z wiersza poleceń, jeśli to możliwe, i zostanie wygenerowany jako pojedynczy element. Jeśli nie ma argumentu wiersza poleceń, zostanie wygenerowana wartość domyślna.

Matas Vaitkevicius
źródło
3
Należy jednak zauważyć, że nargs='?'nie tworzy listy.
Acumenus,
@ABB Ostatni wiersz odpowiedzi Generally this means a single command-line argument will be consumed and a single item (not a list) will be produced.Mam nadzieję, że to pomoże ...
Matas Vaitkevicius,
1
Cytowany wiersz odnosi się do przypadku nieokreślenia nargs, ale nargs='?'definiuje go. W docs powiedzieć: '?'. Jeden argument zostanie wykorzystany z linii poleceń, jeśli to możliwe, i zostanie wygenerowany jako pojedynczy element. Jeśli nie ma argumentu wiersza poleceń, zostanie wygenerowana wartość domyślna.
Acumenus,
@ABB Po prostu edytuj odpowiedź, jeśli uważasz, że czegoś brakuje. Dzięki.
Matas Vaitkevicius
Jaka jest różnica między nargs=argparse.REMAINDERi nargs='*', jak mi się wydaje, są identyczne pod względem działania (testowane w Python 2.7.10 i Python 3.6.1)?
-5

parser.add_argumentwymaga również przełącznika . Możesz użyć required=False. Oto przykładowy fragment kodu w Pythonie 2.7:

parser = argparse.ArgumentParser(description='get dir')
parser.add_argument('--dir', type=str, help='dir', default=os.getcwd(), required=False)
args = parser.parse_args()
rakhee
źródło
11
OP pytał o parametry pozycyjne, a nie „-dir”. „wymagany” jest nieprawidłowym argumentem dla pozycji. A „fałsz” był literówką, miała na myśli „fałsz”. +1 dla początkujących, -1 dla niechlujstwa.
SoloPilot,