2010-12-06 16 views
2

J'utilise Argparser pour gérer les arguments de mon prog CLI. Mais avec le temps, je pense que ce n'est pas une bonne idée de l'utiliser. Voici le problème. Je veux utiliser des options sans aucun caractère de préfixe. Comme git commit ou svn move. J'ai cherché un peu et trouvé que Argparse a une méthode add_subparser(). Laissez-nous remplissons notre foo prog:Est-il possible de définir des options sans préfixe dans Argparser?

parser = argparse.ArgumentParser(prog='foo', usage='%(prog)s [options]') 

subparsers = parser.add_subparsers(help='sub-command help') 
parser_a = subparsers.add_parser('add', help='a help') 
parser_a.add_argument('-ap', '--add-project', 
        nargs='*', 
        action='store', 
        help="Add project") 

parser_d = subparsers.add_parser('del', help='a help') 
parser_d.add_argument('-dp', '--delete-project', 
        nargs='*', 
        action='store', 
        help="Delete project") 

args = parser.parser_args() 

Maintenant, nous allons exécuter foo avec des options et impression espace de noms args (je ne l'ai pas passé tout le code, vous obtenez le point):

$ ./foo del 
Namespace(delete_project=None) 
$ ./foo add 
Namespace(add_project=None) 

Comme vous le voyez, si j'exécute l'option del, add_project n'est pas passé à la variable args. Cela provoque des problèmes si j'ai un « si la clause » dans ma fonction principale() comme

def main(args): 

    if args.delete_project: 
     ... 
    if args.add_project: 
     ... 

Je vais un AttributeError exception, que l'espace de noms n'a pas d'attribut avec le nom add_project si j'exécute ./foo del. En outre, je ne peux pas passer d'argument aux options del et add. J'ai également défini prefix_chars à une chaîne vide, cela n'a pas fonctionné non plus.

Quelle est la façon de le gérer? Argparse est-il capable de créer des options comme git, svn, etc. ou dois-je créer ma propre fonction et gérer tous les arguments moi-même?

Répondre

0

Au lieu de votre instruction if, the argparse docs recommend something like this:

parser_X.set_defaults(action=action_func) 
args.action(args) 

Ensuite, la add_action se penchera sur add_project et del_action à del_project.

+0

C'est absolument le cas.L'OP obtient des erreurs d'attribut sur les sous -parateurs que l'utilisateur n'a pas invoqués, et je lui ai expliqué comment regarder le sous-analyseur utilisé. – Tobu

+0

Bah, mon erreur, j'ai complètement raté le 'subparser'. –

+0

@Nick Heh. C'était un peu laconique, je laisse l'explication. – Tobu

0

Edit: Apparemment, la valeur par défaut pour default est None, ce qui signifie que nous n'avons un, vous devrez utiliser True et False (ce qui est la bonne façon de toute façon).

Vous devez ajouter le default lorsque vous ajoutez votre argument à l'analyseur:

parser_a.add_argument('-ap', '--add-project', 
        nargs = '*', 
        action = 'store_true', 
        default = False, 
        help = "Add project") 

Vous pouvez voir la documentation de la méthode add_argumenthere. (Je me rends compte que la mise en page doc argparse n'est pas la plus propice pour comprendre comment faire des choses qui ne sont pas rappelées dans les exemples)

Aussi, comme Tobu le signale de manière appropriée dans sa réponse, les sous-joueurs inutilisés ne font pas t être invoqué, vous ne pouvez donc pas sonder leurs valeurs en toute sécurité sans au moins protéger votre code dans un bloc try:. Cependant, vous devriez vraiment utiliser la fonctionnalité d'associer un action avec vos sous-parties, sauf si vous avez une situation beaucoup plus complexe où ils ont besoin de partager l'état.

+1

* L'argument mot-clé par défaut de add_argument(), dont la valeur par défaut est None ... Il ne résout pas ce problème. Il ne passe toujours pas add_project si j'exécute 'foo del' –

+0

@Farslan: Bah, donc vraiment vous êtes obligé d'utiliser' True' et 'False' alors (et donc vraiment' store_true' et 'store_false' dans votre action) –