Argparse argumentos posicionais opcionais?

652

Eu tenho um script que deve ser usado assim: usage: installer.py dir [-h] [-v]

dir é um argumento posicional que é definido assim:

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

Quero dirque seja opcional: quando não for especificado, deve ser apenas cwd.

Infelizmente, quando não especifico o dirargumento, recebo Error: Too few arguments.

Waldo Bronchart
fonte

Respostas:

825

Use nargs='?'(ou nargs='*' se você precisar de mais de um diretório)

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

exemplo estendido:

>>> 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
fonte
14
O ?e *significa o mesmo que eles significam em expressões regulares (isto é, ?requer 0 ou 1 e *requer 0 ou mais)? Se sim, também +funciona?
Dolan Antenucci
37
@dolan: Sim, também +funciona. Consulte docs.python.org/2/library/argparse.html#nargs para obter detalhes.
Vinay Sajip
2
existe alguma maneira de obter dir para aparecer em argumentos opcionais? ou parece que os argumentos posicionais devem ter um qualificador 'opcional' precedente. é possível registrá-lo (no que diz respeito à ajuda) como tal?
Scagnetti
6
@ant Do acima exposto, você pode ver que dir é opcional (que aparece entre colchetes na saída argparse indica isso).
Vinay Sajip
1
Tx! Dir dir de options.dir, não args.dir, como eu estava tentando!
PTIM
69

Como uma extensão da resposta @VinaySajip. Há adicional nargsvale a pena mencionar .

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

N (um número inteiro). N argumentos da linha de comando serão reunidos em uma lista

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

'*'. Todos os argumentos da linha de comando presentes são reunidos em uma lista. Observe que geralmente não faz muito sentido ter mais de um argumento posicional nargs='*', mas vários argumentos opcionais nargs='*'são possíveis.

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

'+'. Assim como '*', todos os argumentos de linha de comando presentes são reunidos em uma lista. Além disso, uma mensagem de erro será gerada se não houver pelo menos um argumento de linha de comando presente.

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

argparse.REMAINDER. Todos os demais argumentos da linha de comando são reunidos em uma lista. Isso é geralmente útil para utilitários de linha de comando que são enviados para outros utilitários de linha de comando

Se o nargs argumento palavra chave não for fornecido, o número de argumentos consumidos será determinado pela ação. Geralmente, isso significa que um único argumento de linha de comando será consumido e um único item (não uma lista) será produzido.

Editar (copiado de um comentário por @Acumenus) nargs='?' Os documentos dizem: '?'. Um argumento será consumido na linha de comando, se possível, e produzido como um único item. Se nenhum argumento da linha de comando estiver presente, o valor do padrão será produzido.

Matas Vaitkevicius
fonte
3
Note-se, no entanto, que nargs='?'não produz uma lista.
Acumenus 5/10
@ABB Última linha da resposta Generally this means a single command-line argument will be consumed and a single item (not a list) will be produced.Espero que ajude ...
Matas Vaitkevicius
1
A linha citada refere-se ao caso de não definir nargs, mas nargs='?'está definindo-o. Os documentos dizem: '?'. Um argumento será consumido na linha de comando, se possível, e produzido como um único item. Se nenhum argumento da linha de comando estiver presente, o valor do padrão será produzido.
Acumenus 05/10
@ABB Basta editar a resposta se achar que algo está faltando. Obrigado.
Matas Vaitkevicius 5/10
Qual é a diferença entre nargs=argparse.REMAINDERe nargs='*', como me parece, eles são idênticos em seus efeitos (testados no Python 2.7.10 e Python 3.6.1)?
-5

parser.add_argumenttambém possui uma chave necessária . Você pode usar required=False. Aqui está um trecho de amostra com o Python 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
fonte
11
O OP estava perguntando sobre parâmetros posicionais, não '--dir'. 'required' é um argumento inválido para posicionais. E "falso" era um erro de digitação, ela queria dizer "falso". +1 para iniciante, -1 para negligência.
SoloPilot 4/12/16