web-dev-qa-db-fra.com

comment rendre l'argument facultatif dans python argparse

Je voudrais faire fonctionner ces invocations de myprog, et pas d'autres.

$ python3 myprog.py -i infile -o outfile
$ python3 myprog.py -o outfile
$ python3 myprog.py -o
$ python3 myprog.py 

En particulier, je veux rendre illégal la spécification de l'infile mais pas du outfile.

Dans le troisième cas, un nom par défaut pour le fichier de sortie est supposé, "out.json". Dans les deuxième, troisième et quatrième cas, un nom par défaut pour le fichier d'entrée est supposé, "file.n.json", où n est un numéro de version entier. Dans le quatrième cas, le fichier de sortie serait "file.n + 1.json" où n + 1 est un numéro de version un plus grand que celui du fichier d'entrée. La section pertinente de mon code est:

import argparse

parser = argparse.ArgumentParser(description="first python version")
parser.add_argument('-i', '--infile', nargs=1, type=argparse.FileType('r'), help='input file, in JSON format')
parser.add_argument('-o', '--outfile', nargs='?', type=argparse.FileType('w'), default='out.json', help='output file, in JSON format')

args = parser.parse_args()

print("Here's what we saw on the command line: ")
print("args.infile",args.infile)
print("args.outfile",args.outfile)

if args.infile and not args.outfile:
    parser.error("dont specify an infile without specifying an outfile")
Elif not args.infile:
    print("fetching infile")
else: # neither was specified on the command line
    print("fetching both infile and outfile")

Le problème est, quand je cours

$ python3 myprog.py -i infile.json

au lieu de l'erreur d'analyseur que j'espérais, j'obtiens:

Here's what we saw on the command line: 
args.infile [<_io.TextIOWrapper name='infile.json' mode='r' encoding='UTF-8'>]
args.outfile <_io.TextIOWrapper name='out.json' mode='w' encoding='UTF-8'>
fetching both infile and outfile

... ce qui suggère que même s'il n'y avait pas de "-o" sur la ligne de commande, il se comportait comme s'il y en avait.

27
user1416227

Vous avez spécifié un argument par défaut pour le fichier de sortie.

parser.add_argument('-o', '--outfile', nargs='?', type=argparse.FileType('w'), default='out.json', help='output file, in JSON format')

Si l'option -o N'est pas spécifiée sur la ligne de commande, l'analyseur arg insère l'argument par défaut.

Changez ceci en:

parser.add_argument('-o', '--outfile', nargs='?', type=argparse.FileType('w'), help='output file, in JSON format')

et les choses devraient fonctionner comme prévu.


Si vous voulez pouvoir spécifier -o, Sans nom de fichier, vous voulez probablement quelque chose comme:

out_file = args.out if args.out is not None else 'json.out'

Je ne sais pas si le paramètre pertinent sera None ou '' (C'est-à-dire une chaîne vide) si vous spécifiez le -o Sans paramètre - je soupçonne que c'est None, mais je ne sais pas avec certitude. Vous devrez le tester pour en être sûr.

Je ne sais pas comment faire cela sans logique supplémentaire avec argparse.

13
BenDundee

En complément de la réponse sélectionnée:

L'option d'exécuter -o sans spécifier de fichier, peut être fait en utilisant const combiné avec nargs='?'.

De la documentation:

Lorsque add_argument () est appelé avec des chaînes d'options (comme -f ou --foo) et nargs = '?'. Cela crée un argument facultatif qui peut être suivi de zéro ou d'un argument de ligne de commande. Lors de l'analyse de la ligne de commande, si la chaîne d'option est rencontrée sans argument de ligne de commande qui la suit, la valeur de const sera supposée à la place. Voir la description des nargs pour des exemples.

16
mhristache