TL; DR
Use a nargs
opção ou a 'append'
configuração da action
opção (dependendo de como você deseja que a interface do usuário se comporte).
nargs
parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567
nargs='+'
leva 1 ou mais argumentos, nargs='*'
leva zero ou mais.
acrescentar
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
Com append
você, forneça a opção várias vezes para criar a lista.
Não use type=list
!!! - Provavelmente, não há situação em que você gostaria de usar type=list
com argparse
. Sempre.
Vamos dar uma olhada em mais detalhes em algumas das maneiras diferentes de tentar fazer isso e no resultado final.
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)
Aqui está a saída que você pode esperar:
$ 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']
Takeaways :
- Use
nargs
ouaction='append'
nargs
pode ser mais direto da perspectiva do usuário, mas pode não ser intuitivo se houver argumentos posicionais, porque argparse
não é possível dizer o que deve ser um argumento posicional e o que pertence ao nargs
; se você tiver argumentos posicionais, action='append'
pode acabar sendo uma escolha melhor.
- O acima só é verdadeiro se
nargs
é dada '*'
, '+'
ou '?'
. Se você fornecer um número inteiro (como 4
), não haverá problema em misturar opções com nargs
argumentos posicionais, pois argparse
saberá exatamente quantos valores esperar para a opção.
- Não use aspas na linha de comando 1
- Não use
type=list
, pois ele retornará uma lista de listas
- Isso acontece porque, sob o capô,
argparse
usa o valor de type
para coagir cada argumento que você escolheu type
, e não o agregado de todos os argumentos.
- Você pode usar
type=int
(ou o que for) para obter uma lista de entradas (ou o que for)
1 : Não quero dizer em geral. Quero dizer, usar aspas para passar uma listaargparse
não é o que você deseja.
type=list
opção. Não use isso. Isso transforma uma string em uma lista e, portanto, nas listas de listas.type
parâmetro para outro objeto. Por padrão, esse método retorna uma lista de strings.--
poderia dividir opções versus argumentos posicionais.prog --opt1 par1 ... -- posp1 posp2 ...
--
ajuda a descobrir isso, como mostra o exemplo no meu comentário anterior. Suprimentos de usuário IOW--
seguidos por todos os argumentos posicionais.Prefiro passar uma string delimitada que analiso posteriormente no script. As razões para isso são; a lista pode ser de qualquer tipo
int
oustr
, e às vezes usandonargs
problemas, se houver vários argumentos opcionais e argumentos posicionais.Então,
ou,
vai funcionar bem. O delimitador também pode ser um espaço, o que aplicaria aspas ao redor do valor do argumento, como no exemplo da pergunta.
fonte
type
argumento para emlambda s: [int(time) for item in s.split(',')]
vez de pós-processamentoargs.list
.int(time)
deveria serint(item)
. Meu exemplo foi uma versão simplificada do que normalmente faço, onde verifico muitas outras coisas, em vez de um simples processamento. Mas, para simplesmente responder à pergunta, também acho o seu caminho mais elegante. #lambda items: list(csv.reader([items]))[0]
com a biblioteca csv padrão é uma versão modificada do comentário do @chepner para qualquer pessoa preocupada com a entrada arbitrária de CSV (ref: answer from @adamk ).Além disso
nargs
, você pode usarchoices
se souber a lista com antecedência:fonte
Usando o parâmetro nargs no método add_argument do argparse
Eu uso nargs = ' ' como um parâmetro add_argument. Eu usei especificamente nargs = ' ' para a opção de escolher padrões se eu não estiver passando nenhum argumento explícito
Incluindo um trecho de código como exemplo:
Exemplo: temp_args1.py
Observe: O código de exemplo abaixo está escrito em python3. Alterando o formato da instrução print, pode ser executado em python2
Nota: Estou coletando vários argumentos de seqüência de caracteres que são armazenados na lista - opts.alist Se você quiser uma lista de números inteiros, altere o parâmetro type em parser.add_argument para int
Resultado da execução:
fonte
temp_args1.py -i [item5 ,item6, item7]
e ter a saída de sair como uma lista bem (em vez de lista aninhada)Se você pretende fazer um único comutador usar vários parâmetros, use-o
nargs='+'
. Se o seu exemplo '-l' estiver usando números inteiros:Produz
Se você especificar o mesmo argumento várias vezes, a ação padrão (
'store'
) substituirá os dados existentes.A alternativa é usar a
append
ação:O que produz
Ou você pode escrever um manipulador / ação personalizado para analisar valores separados por vírgula, para que você possa executar
fonte
In
add_argument()
,type
é apenas um objeto que pode ser chamado que recebe uma string e retorna o valor da opção.Isso permitirá:
fonte
Se você possui uma lista aninhada em que as listas internas têm diferentes tipos e comprimentos e deseja preservar o tipo, por exemplo,
[[1, 2], ["foo", "bar"], [3.14, "baz", 20]]
então você pode usar a solução proposta por @ sam-mason para esta pergunta , mostrada abaixo:
que dá:
fonte
Eu quero lidar com a passagem de várias listas, valores inteiros e seqüências de caracteres.
Link útil => Como passar uma variável Bash para Python?
A ordem não é importante. Se você quiser passar uma lista, faça como entre
"["
e"]
e separá-los usando uma vírgula.Então,
Saída =>
['my_string', '3', ['1', '2'], ['3', '4', '5']]
,my_args
variável contém os argumentos em ordem.fonte
Eu acho que a solução mais elegante é passar uma função lambda para "type", como mencionado por Chepner. Além disso, se você não souber de antemão qual será o delimitador da sua lista, também poderá passar vários delimitadores para re.split:
fonte
-l
na chamada de exemplo? De onde-n
veio?parser.add_argument('-l', '--list', type = lambda s: re.split('[ ,;]', s))
. Aqui é a entrada:script.py -l abc xyz, abc\nxyz
. Finalmente, aqui está o resultado:script.py: error: unrecognized arguments: xyz, abcnxyz