Eu gostaria de usar argparse para analisar argumentos booleanos da linha de comando escritos como "--foo True" ou "--foo True". Por exemplo:
my_program --my_boolean_flag False
No entanto, o código de teste a seguir não faz o que eu gostaria:
import argparse
parser = argparse.ArgumentParser(description="My parser")
parser.add_argument("--my_bool", type=bool)
cmd_line = ["--my_bool", "False"]
parsed_args = parser.parse(cmd_line)
Infelizmente, parsed_args.my_bool
avalia como True
. Este é o caso mesmo quando eu mudo cmd_line
para ser ["--my_bool", ""]
, o que é surpreendente, já que é bool("")
avaliado em False
.
Como posso obter argparse para analisar "False"
, "F"
e sua minúscula variantes para ser False
?
python
boolean
argparse
command-line-parsing
SuperElectric
fonte
fonte
parser.add_argument('--feature', dest='feature', default=False, action='store_true')
. Essa solução garante que você sempre obtenha umbool
tipo com valorTrue
ouFalse
. (Esta solução tem uma restrição: a sua opção deve ter um valor padrão.)parser.add_argument('--feature', dest='feature', type=lambda x:bool(distutils.util.strtobool(x)))
. Quando a opção é usada, esta solução garante umbool
tipo com valor deTrue
ouFalse
. Quando a opção não for usada, você receberáNone
. (distutils.util.strtobool(x)
É de outra questão stackoverflow )parser.add_argument('--my_bool', action='store_true', default=False)
Respostas:
Outra solução usando as sugestões anteriores, mas com o erro de análise "correto" de
argparse
:Isso é muito útil para fazer trocas com valores padrão; por exemplo
me permite usar:
e ainda use um valor padrão (específico para as configurações do usuário). Uma desvantagem (relacionada indiretamente) com essa abordagem é que os 'nargs' podem pegar um argumento posicional - veja esta questão relacionada e este relatório de erro da argparse .
fonte
str2bool(v)
poderia ser substituído porbool(distutils.util.strtobool(v))
. Fonte: stackoverflow.com/a/18472142/2436175if args.nice:
beacuse, se o argumento estiver definido como False, nunca passará a condição. Se isso é certo, então talvez seja melhor a lista retornar destr2bool
função e set list comoconst
parâmetro, como este[True]
,[False]
. Corrija-me se eu estiver erradoEu acho que uma maneira mais canônica de fazer isso é via:
e
argparse
suporta bem esta versão:Obviamente, se você realmente deseja a
--arg <True|False>
versão, pode passarast.literal_eval
como o "tipo" ou uma função definida pelo usuário ...fonte
type=bool
deveria funcionar imediatamente (considere argumentos posicionais!). Mesmo quando você especifica adicionalmentechoices=[False,True]
, você acaba com "False" e "True" considerados True (devido a uma conversão de string para bool?). Talvez problema relacionado #bool()
função Python deve fazer ou o que o argparse deve aceitartype=fn
? Todas asargparse
verificações é quefn
é exigível. Ele esperafn
receber um argumento de sequência e retornar um valor. O comportamento defn
é de responsabilidade do programador, nãoargparse's
.Eu recomendo a resposta de mgilson, mas com um grupo mutuamente exclusivo,
para que você não possa usar
--feature
e--no-feature
ao mesmo tempo.e
mas não
Roteiro:
Você pode usar esse auxiliar se quiser definir muitos deles:
fonte
add_argument
é chamado comdest='feature'
.set_defaults
é chamado comfeature=True
. Compreendo?--flag False
, parte das respostas do SO deveria ser sobre O QUE eles estão tentando resolver, não apenas COMO. Deve haver absolutamente nenhuma razão para fazer--flag False
ou--other-flag True
e, em seguida, usar algum analisador personalizado para converter a string para um boolean ..action='store_true'
eaction='store_false'
são as melhores maneiras de usar bandeiras booleanas... can be “don’t do that”, but it should also include “try this instead”
que (pelo menos para mim) implica respostas deve ser mais profunda quando apropriado. Definitivamente, há momentos em que alguns de nós que postamos perguntas podem se beneficiar de orientações sobre melhores / melhores práticas, etc. Responder "como indicado" geralmente não faz isso. Dito isto, sua frustração com as respostas geralmente assumindo muito (ou incorretamente) é completamente válida.parser.set_defaults(feature=None)
help=
entrada para esse argumento, para onde deveria ir? Naadd_mutually_exclusive_group()
ligação? Em uma ou nas duasadd_argument()
chamadas? Em outro lugar?Aqui está outra variação sem linhas extras para definir os valores padrão. O bool sempre tem um valor atribuído para que possa ser usado em instruções lógicas sem pré-verificações.
fonte
required=True
ou você sempre obterá um argumento True.python3 test.py --do-something False
falha comerror: unrecognized arguments: False
, por isso realmente não responde à pergunta.oneliner:
fonte
type=lambda x: (str(x).lower() in ['true','1', 'yes'])
Parece haver alguma confusão sobre o que
type=bool
etype='bool'
pode significar. Um (ou ambos) deve significar 'executar a funçãobool()
ou' retornar um booleano '? Tal como estátype='bool'
, não significa nada.add_argument
dá um'bool' is not callable
erro, igual ao que você usoutype='foobar'
, outype='int'
.Mas
argparse
possui um registro que permite definir palavras-chave como esta. É usado principalmente paraaction
, por exemplo, `action = 'store_true'. Você pode ver as palavras-chave registradas com:que exibe um dicionário
Existem muitas ações definidas, mas apenas um tipo, o padrão
argparse.identity
,.Este código define uma palavra-chave 'bool':
parser.register()
não está documentado, mas também não está oculto. Para a maior parte o programador não precisa saber sobre isso, porquetype
eaction
função take e de classe valores. Existem muitos exemplos de stackoverflow para definir valores personalizados para ambos.Caso isso não seja óbvio na discussão anterior,
bool()
não significa 'analisar uma string'. Na documentação do Python:Compare isso com
fonte
Eu estava procurando o mesmo problema, e imho a solução bonita é:
e usando isso para analisar a string como booleana, conforme sugerido acima.
fonte
distutils.util.strtobool(v)
.distutils.util.strtobool
retornos 1 ou 0, e não um booleano real.Uma maneira bastante semelhante é usar:
e se você definir o argumento --feature em seu comando
o argumento será True, se você não definir type --feature, o argumento default será sempre False!
fonte
--feature False
Além do que o @mgilson disse, deve-se notar que também há um
ArgumentParser.add_mutually_exclusive_group(required=False)
método que tornaria trivial impor isso--flag
e--no-flag
não é usado ao mesmo tempo.fonte
Isso funciona para tudo o que eu espero:
O código:
fonte
_str_to_bool(s)
para converters = s.lower()
uma vez, depois testarif s not in {'true', 'false', '1', '0'}
e finalmentereturn s in {'true', '1'}
.Uma maneira mais simples seria usar como abaixo.
fonte
Mais simples. Não é flexível, mas prefiro a simplicidade.
EDIT: Se você não confia na entrada, não use
eval
.fonte
eval
é uma função interna. docs.python.org/3/library/functions.html#eval Essa pode ser uma função unária que outras abordagens mais flexíveis aproveitam.A maneira mais simples seria usar as opções :
Não passando --my-flag é avaliado como False. A opção required = True pode ser adicionada se você sempre quiser que o usuário especifique explicitamente uma opção.
fonte
Eu acho que a maneira mais canônica será:
fonte
fonte
A maneira mais simples e correta é
Observe que os valores verdadeiros são y, sim, t, verdadeiro, ativado e 1; valores falsos são n, não, f, falso, desligado e 0. Gera ValueError se val for outra coisa.
fonte
Rápido e fácil, mas apenas para argumentos 0 ou 1:
A saída será "False" após a chamada do terminal:
fonte
Semelhante ao Akash, mas aqui está outra abordagem que eu usei. Ele usa do
str
quelambda
porque pythonlambda
sempre me dá um sentimento estranho.fonte
Como uma melhoria na resposta de @Akash Desarda, você pode fazer
E suporta
python test.py --foo
fonte