TL; DR
Skorzystaj z nargs
opcji lub jej 'append'
ustawienia action
(w zależności od tego, jak ma się zachowywać interfejs użytkownika).
nargs
parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567
nargs='+'
przyjmuje 1 lub więcej argumentów, nargs='*'
przyjmuje zero lub więcej.
dodać
parser.add_argument('-l','--list', action='append', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 -l 2345 -l 3456 -l 4567
Dzięki append
wielokrotnej opcji możesz zbudować listę.
Nie używaj type=list
!!! - Prawdopodobnie nie ma sytuacji, w której chciałbyś używać type=list
z argparse
. Zawsze.
Przyjrzyjmy się bardziej szczegółowo niektórym różnym sposobom, w jakie można to zrobić, i efektowi końcowemu.
import argparse
parser = argparse.ArgumentParser()
# By default it will fail with multiple arguments.
parser.add_argument('--default')
# Telling the type to be a list will also fail for multiple arguments,
# but give incorrect results for a single argument.
parser.add_argument('--list-type', type=list)
# This will allow you to provide multiple arguments, but you will get
# a list of lists which is not desired.
parser.add_argument('--list-type-nargs', type=list, nargs='+')
# This is the correct way to handle accepting multiple arguments.
# '+' == 1 or more.
# '*' == 0 or more.
# '?' == 0 or 1.
# An int is an explicit number of arguments to accept.
parser.add_argument('--nargs', nargs='+')
# To make the input integers
parser.add_argument('--nargs-int-type', nargs='+', type=int)
# An alternate way to accept multiple inputs, but you must
# provide the flag once per input. Of course, you can use
# type=int here if you want.
parser.add_argument('--append-action', action='append')
# To show the results of the given option to screen.
for _, value in parser.parse_args()._get_kwargs():
if value is not None:
print(value)
Oto wynik, którego możesz się spodziewać:
$ python arg.py --default 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567
$ python arg.py --list-type 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567
$ # Quotes won't help here...
$ python arg.py --list-type "1234 2345 3456 4567"
['1', '2', '3', '4', ' ', '2', '3', '4', '5', ' ', '3', '4', '5', '6', ' ', '4', '5', '6', '7']
$ python arg.py --list-type-nargs 1234 2345 3456 4567
[['1', '2', '3', '4'], ['2', '3', '4', '5'], ['3', '4', '5', '6'], ['4', '5', '6', '7']]
$ python arg.py --nargs 1234 2345 3456 4567
['1234', '2345', '3456', '4567']
$ python arg.py --nargs-int-type 1234 2345 3456 4567
[1234, 2345, 3456, 4567]
$ # Negative numbers are handled perfectly fine out of the box.
$ python arg.py --nargs-int-type -1234 2345 -3456 4567
[-1234, 2345, -3456, 4567]
$ python arg.py --append-action 1234 --append-action 2345 --append-action 3456 --append-action 4567
['1234', '2345', '3456', '4567']
Na wynos :
- Użyj
nargs
lubaction='append'
nargs
może być prostsze z punktu widzenia użytkownika, ale może być nieintuicyjne, jeśli istnieją argumenty pozycyjne, ponieważ argparse
nie można powiedzieć, co powinno być argumentem pozycyjnym, a co należy do nargs
; jeśli masz argumenty pozycyjne, action='append'
może być lepszym wyborem.
- Powyższe jest prawdziwe tylko wtedy, gdy
nargs
jest podany '*'
, '+'
lub '?'
. Jeśli podasz liczbę całkowitą (np. 4
), Nie będzie problemu z mieszaniem opcji z nargs
argumentami pozycyjnymi, ponieważ argparse
będziesz wiedział dokładnie, ile wartości można oczekiwać dla opcji.
- Nie używaj cudzysłowów w wierszu poleceń 1
- Nie używaj
type=list
, ponieważ spowoduje to zwrócenie listy list
- Dzieje się tak, ponieważ pod maską
argparse
używa się wartości, type
aby wymusić każdy wybrany argumenttype
, a nie sumę wszystkich argumentów.
- Możesz użyć
type=int
(lub cokolwiek), aby uzyskać listę ints (lub cokolwiek)
1 : Ogólnie nie mam na myśli .. Mam na myśli, że przekazywanie listyargparse
cudzysłowami nie jest tym, czego chcesz.
type=list
opcji. Nie używaj tego. To zamienia ciąg znaków w listę, a tym samym listy list.type
parametr zostanie ustawiony na inny obiekt. Domyślnie ta metoda zwraca listę ciągów znaków.--
może podzielić opcje na argumenty pozycyjne.prog --opt1 par1 ... -- posp1 posp2 ...
--
pomaga to rozgryźć, jak pokazano na przykładzie w poprzednim komentarzu. Dostawy IOW użytkownika--
wraz z wszystkimi argumentami pozycyjnymi.Wolę przekazywać ciąg ograniczony, który analizuję później w skrypcie. Przyczyny tego są; lista może być dowolnego typu
int
lubstr
, a czasem przy użyciunargs
I napotkał problemy, jeśli istnieje wiele argumentów opcjonalnych i argumentów pozycyjnych.Następnie,
lub,
będzie dobrze działać. Separator może być również spacją, która wymusiłaby cytaty wokół wartości argumentu, jak w przykładzie w pytaniu.
źródło
type
argument nalambda s: [int(time) for item in s.split(',')]
zamiast przetwarzania końcowegoargs.list
.int(time)
powinno byćint(item)
. Mój przykład był uproszczoną wersją tego, co zwykle robię, gdzie sprawdzam wiele innych rzeczy, a nie proste przetwarzanie. Ale po prostu odpowiadając na pytanie, ja też uważam twoją drogę za bardziej elegancką ..lambda items: list(csv.reader([items]))[0]
ze standardową biblioteką csv jest zmodyfikowaną wersją komentarza od @chepner dla każdego, kto martwi się o arbitralne dane wejściowe CSV (zob .: odpowiedź od @adamk ).Ponadto
nargs
możesz skorzystać,choices
jeśli znasz listę z góry:źródło
Użycie parametru nargs w metodzie add_argument argparse
Używam nargs = ' ' jako parametru add_argument. W szczególności użyłem nargs = ' ' do opcji wyboru wartości domyślnych, jeśli nie przekazuję żadnych wyraźnych argumentów
W tym fragment kodu jako przykład:
Przykład: temp_args1.py
Uwaga: poniższy przykładowy kod został napisany w python3. Zmieniając format instrukcji print, można uruchomić w python2
Uwaga: zbieram wiele argumentów łańcuchowych, które są przechowywane na liście - opts.alist Jeśli chcesz listę liczb całkowitych, zmień parametr type w parser.add_argument na int
Wynik wykonania:
źródło
temp_args1.py -i [item5 ,item6, item7]
iJeśli zamierzasz sprawić, aby pojedynczy przełącznik przyjmował wiele parametrów, użyj
nargs='+'
. Jeśli twój przykład „-l” faktycznie przyjmuje liczby całkowite:Produkuje
Jeśli podasz ten sam argument wiele razy, domyślna akcja (
'store'
) zastępuje istniejące dane.Alternatywą jest użycie
append
akcji:Który produkuje
Możesz też napisać niestandardowy moduł obsługi / akcji, aby przeanalizować wartości oddzielone przecinkami, abyś mógł to zrobić
źródło
w
add_argument()
,type
jest po prostu wywoływalnym obiekt, który odbiera ciąg i zwraca wartość opcji.Umożliwi to:
źródło
Jeśli masz zagnieżdżoną listę, w której wewnętrzne listy mają różne typy i długości i chcesz zachować typ, np.
[[1, 2], ["foo", "bar"], [3.14, "baz", 20]]
możesz skorzystać z rozwiązania zaproponowanego przez @ sam-mason na to pytanie , pokazanego poniżej:
co daje:
źródło
Chcę obsłużyć przekazywanie wielu list, wartości całkowitych i ciągów.
Pomocny link => Jak przekazać zmienną Bash do Pythona?
Porządek nie jest ważny. Jeśli chcesz przekazać listę prostu zrobić jak między
"["
a"]
i oddzielić je za pomocą przecinka.Następnie,
Dane wyjściowe =>
['my_string', '3', ['1', '2'], ['3', '4', '5']]
,my_args
zmienna zawiera argumenty w kolejności.źródło
Myślę, że najbardziej eleganckim rozwiązaniem jest przekazanie funkcji lambda do „pisma”, jak wspomniał Chepner. Ponadto, jeśli wcześniej nie wiesz, jaki będzie separator listy, możesz również przekazać wiele separatorów do re.split:
źródło
-l
o przykładowe połączenie? Skąd się wziął-n
?parser.add_argument('-l', '--list', type = lambda s: re.split('[ ,;]', s))
. Tutaj jest wejście:script.py -l abc xyz, abc\nxyz
. Wreszcie, oto wynik:script.py: error: unrecognized arguments: xyz, abcnxyz