Argparse arguments positionnels optionnels?

652

J'ai un script qui est destiné à être utilisé comme ceci: usage: installer.py dir [-h] [-v]

dir est un argument positionnel qui est défini comme ceci:

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

Je veux que ce dirsoit facultatif: quand il n'est pas spécifié, il devrait l'être cwd.

Malheureusement, quand je ne spécifie pas l' dirargument, j'obtiens Error: Too few arguments.

Waldo Bronchart
la source

Réponses:

825

Utilisez nargs='?'(ou nargs='*' si vous aurez besoin de plus d'un dir)

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

exemple étendu:

>>> 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
la source
14
Est-ce que le ?et *signifient la même chose qu'ils signifient dans les expressions régulières (c. ?-à-d. *Nécessite 0 ou 1 et 0 ou plus)? Si oui, ça +marche aussi?
Dolan Antenucci
37
@dolan: Oui, ça +marche aussi. Voir docs.python.org/2/library/argparse.html#nargs pour les détails.
Vinay Sajip
2
existe-t-il un moyen d'obtenir dir pour apparaître dans les arguments facultatifs? ou il semble que les arguments positionnels devraient avoir un qualificatif «facultatif» précédent. est-il possible de l'enregistrer (en ce qui concerne l'aide) en tant que tel?
scagnetti
6
@ant D'après ce qui précède, vous pouvez voir que dir est facultatif (qu'il apparaît entre crochets dans la sortie argparse indique cela).
Vinay Sajip du
1
Tx! Accès depuis options.dir, non args.dir, comme j'essayais!
ptim
69

En tant qu'extension de la réponse @VinaySajip. Il y en a d'autres qui nargsméritent d'être mentionnés .

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

N (un entier). N arguments de la ligne de commande seront regroupés dans une liste

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

'*'. Tous les arguments de ligne de commande présents sont regroupés dans une liste. Notez qu'il n'a généralement pas beaucoup de sens d'avoir plus d'un argument positionnel avec nargs='*', mais plusieurs arguments optionnels avec nargs='*'sont possibles.

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

'+'. Tout comme «*», tous les arguments de ligne de commande présents sont regroupés dans une liste. De plus, un message d'erreur sera généré s'il n'y avait pas au moins un argument de ligne de commande présent.

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

argparse.REMAINDER. Tous les arguments de ligne de commande restants sont regroupés dans une liste. Ceci est généralement utile pour les utilitaires de ligne de commande qui se répartissent vers d'autres utilitaires de ligne de commande

Si l' nargsargument mot - clé n'est pas fourni, le nombre d'arguments consommés est déterminé par l'action. Cela signifie généralement qu'un seul argument de ligne de commande sera consommé et qu'un seul élément (pas une liste) sera produit.

Modifier (copié à partir d'un commentaire de @Acumenus) nargs='?' Les documents disent: '?'. Un argument sera consommé à partir de la ligne de commande si possible et produit comme un seul élément. Si aucun argument de ligne de commande n'est présent, la valeur par défaut sera produite.

Matas Vaitkevicius
la source
3
Il convient toutefois de noter que nargs='?'cela ne produit pas de liste.
Acumenus du
@ABB Dernière ligne de la réponse Generally this means a single command-line argument will be consumed and a single item (not a list) will be produced.J'espère que cela aide ...
Matas Vaitkevicius
1
La ligne entre guillemets se réfère au cas de ne pas définir nargs, mais le nargs='?'définit. Les documents disent: «?». Un argument sera consommé à partir de la ligne de commande si possible, et produit comme un seul élément. Si aucun argument de ligne de commande n'est présent, la valeur par défaut sera produite.
Acumenus
@ABB Modifiez simplement la réponse si vous pensez qu'il manque quelque chose. Merci.
Matas Vaitkevicius
Quelle est la différence entre nargs=argparse.REMAINDERet nargs='*', comme il me semble, ils sont identiques dans leur effet (testés en Python 2.7.10 et Python 3.6.1)?
-5

parser.add_argumenta également un interrupteur requis . Vous pouvez utiliser required=False. Voici un exemple d'extrait avec 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
la source
11
OP demandait des paramètres de position, pas '--dir'. 'required' n'est pas un argument valide pour les positions. Et «faux» était une faute de frappe, elle voulait dire «faux». +1 pour les débutants, -1 pour la négligence.
SoloPilot