Tenho os seguintes requisitos:
./xyifier --prox --lport lport --rport rport
para o argumento prox, uso action = 'store_true' para verificar se está presente ou não. Eu não exijo nenhum dos argumentos. Mas, se --prox for definido, eu também exijo rport e lport. Existe uma maneira fácil de fazer isso com argparse sem escrever codificação condicional personalizada.
Mais código:
non_int.add_argument('--prox', action='store_true', help='Flag to turn on proxy')
non_int.add_argument('--lport', type=int, help='Listen Port.')
non_int.add_argument('--rport', type=int, help='Proxy port.')
Respostas:
Não, não há nenhuma opção em argparse para criar conjuntos de opções mutuamente inclusivos .
A maneira mais simples de lidar com isso seria:
fonte
parser.error
método, é isso que eu estava procurando!if args.prox and (args.lport is None or args.rport is None):
args.lport is None
, você pode simplesmente usarnot args.lport
. Acho que é um pouco mais pitônico.--lport
ou--rport
para0
, que pode ser uma entrada válida para o programa.Você está falando sobre ter argumentos exigidos condicionalmente. Como @borntyping disse, você pode verificar o erro e fazer isso
parser.error()
, ou pode apenas aplicar um requisito relacionado a--prox
quando adiciona um novo argumento.Uma solução simples para o seu exemplo poderia ser:
Desta forma,
required
recebeTrue
ouFalse
dependendo se o usuário for usado--prox
. Isso também garante que-lport
e-rport
tenham um comportamento independente entre si.fonte
ArgumentParser
pode ser usado para analisar argumentos de uma lista diferente desys.argv
, caso em que isso falharia.--prox=<value>
sintaxe for usada.Que tal usar o
parser.parse_known_args()
método e, em seguida, adicionar os argumentos--lport
e--rport
conforme necessário, se--prox
estiver presente.Além disso, lembre-se de que você pode fornecer o namespace
opts
gerado após a primeira análise, enquanto analisa os argumentos restantes na segunda vez. Dessa forma, no final, depois que toda a análise for feita, você terá um único namespace com todas as opções.Desvantagens:
--prox
não estiver presente, as outras duas opções dependentes nem mesmo estão presentes no namespace. Embora com base no seu caso de uso, se--prox
não estiver presente, o que acontece com as outras opções é irrelevante.--lport
e--rport
não apareça na mensagem de ajudafonte
Você usa
lport
quandoprox
não está definido. Se não, por que não fazerlport
erport
argumentos deprox
? por exemploIsso economiza a digitação dos usuários. É tão fácil de testar
if args.prox is not None:
quantoif args.prox:
.fonte
a,b = args.prox
,a = args.prox[0]
, etc.A resposta aceita funcionou muito bem para mim! Como todo o código é quebrado sem testes, testei a resposta aceita aqui.
parser.error()
não gera umargparse.ArgumentError
erro, em vez disso, sai do processo. Você tem que testarSystemExit
.com pytest
com testes de unidade
inspirado em: Usando unittest para testar argparse - erros de saída
fonte