2016-10-14 2 views
1

Comme le montre le code suivant, je souhaite avoir un argument positionnel optionnel files, je souhaite lui spécifier une valeur par défaut, lorsque des chemins sont passés, utiliser le chemin spécifié.Comment utiliser les arguments positionnels optionnels avec nargs = '*' arguments dans argparse?

Mais parce que --bar peut avoir plusieurs arguments, le chemin passé n'est pas entré dans args.files, comment résoudre ce problème? Merci!

import argparse 
parser = argparse.ArgumentParser() 
parser.add_argument('--foo') 
parser.add_argument('--bar', nargs='*') 
parser.add_argument('files', nargs='?') 

cmd = '--foo a --bar b c d ' 
print parser.parse_args(cmd.split()) 
# Namespace(bar=['b', 'c', 'd'], files=None, foo='a') 


cmd = '--foo a --bar b c d /path/to/file1' 
print parser.parse_args(cmd.split()) 
# Namespace(bar=['b', 'c', 'd', '/path/to/file1'], files=None, foo='a') 
+2

Comment 'argparse' est supposé savoir que'/path/to/file1' va avec 'files' et non avec' bar'? – mgilson

Répondre

1

Votre spec argument est intrinsèquement ambigu (puisque --bar peut prendre des arguments infinis, il n'y a pas de bonne façon de dire quand elle se termine, en particulier depuis files est en option), donc il faut homonymie utilisateur. Plus précisément, argparse peut être dit "c'est la fin de la section des commutateurs, tous les arguments suivants sont positionnels" en mettant -- avant la section positionnelle seulement. Si vous faites:

cmd = '--foo a --bar b c d -- /path/to/file1' 
print parser.parse_args(cmd.split()) 

Vous devriez obtenir:

Namespace(bar=['b', 'c', 'd'], files='/path/to/file1', foo='a') 

(Testé sur AP3, mais devrait appliquer à py2 ainsi)

Alternativement, l'utilisateur peut passer l'argument de position où il est sans ambiguïté en évitant de mettre des arguments positionnels après --bar par exemple:

cmd = '/path/to/file1 --foo a --bar b c d' 

ou

cmd = '--foo a /path/to/file1 --bar b c d' 

Enfin, vous pourriez éviter d'utiliser nargs='*' pour les interrupteurs, étant donné l'ambiguïté qu'il introduit. Au lieu de cela, définir --bar pour être accepté à plusieurs reprises avec une valeur unique par commutateur, accumulant toutes les utilisations à un list:

parser.add_argument('--bar', action='append') 

puis vous passez --bar plusieurs fois pour fournir plusieurs valeurs une à la fois, au lieu de passer une fois avec de nombreuses valeurs:

cmd = '--foo a --bar b --bar c --bar d /path/to/file1'