web-dev-qa-db-fra.com

Argparse avec le sous-analyseur requis

J'utilise Python 3.4, j'essaie d'utiliser argparse avec des sous-analyseurs et je veux avoir un comportement similaire à celui de Python 2.x où si je ne fournis pas d'argument positionnel (pour indiquer le sous-analyseur/sous-programme) j'obtiendrai un message d'erreur utile. C'est-à-dire, avec python2 J'obtiendrai le message d'erreur suivant:

$ python2 subparser_test.py    
usage: subparser_test.py [-h] {foo} ...
subparser_test.py: error: too few arguments

Je configure l'attribut required comme suggéré dans https://stackoverflow.com/a/22994500/3061818 , mais cela me donne une erreur avec Python 3.4.0: TypeError: sequence item 0: expected str instance, NoneType found - traçage complet:

$ python3 subparser_test.py    
Traceback (most recent call last):
  File "subparser_test.py", line 17, in <module>
    args = parser.parse_args()
  File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1717, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1749, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1984, in _parse_known_args
    ', '.join(required_actions))
TypeError: sequence item 0: expected str instance, NoneType found

Ceci est mon programme subparser_test.py - adapté de https://docs.python.org/3.2/library/argparse.html#sub-commands :

import argparse

# sub-command functions
def foo(args):
    print('"foo()" called')

# create the top-level parser
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
subparsers.required = True

# create the parser for the "foo" command
parser_foo = subparsers.add_parser('foo')
parser_foo.set_defaults(func=foo)

args = parser.parse_args()
args.func(args)

Question connexe: Pourquoi ce code argparse se comporte-t-il différemment entre Python 2 et 3?

51
ukrutt

Vous devez donner à subparsers un dest.

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='cmd')
subparsers.required = True

Maintenant:

1909:~/mypy$ argdev/python3 stack23349349.py
usage: stack23349349.py [-h] {foo} ...
stack23349349.py: error: the following arguments are required: cmd

Afin d'émettre ce message d'erreur "arguments manquants", le code doit donner un nom à cet argument. Pour un argument positionnel (comme les sous-analyses), ce nom est (par défaut) le "dest". Il y a une note (mineure) à ce sujet dans la réponse SO que vous avez liée.

L'un des rares "correctifs" à argparse dans la dernière Python version a changé la façon dont il teste les arguments "requis". Malheureusement, il a introduit ce bogue concernant les sous-analyseurs. Cela doit être corrigé dans la prochaine version (sinon plus tôt).

mise à jour

Si vous voulez ce comportement facultatif de sous-analyseurs dans Py2, il semble que la meilleure option consiste à utiliser un analyseur en deux étapes comme décrit dans

Comment définir un sous-analyseur par défaut à l'aide du module Argparse avec Python 2.7

Il y a eu une activité récente dans le bogue/problème connexe

https://bugs.python.org/issue925

mise à jour

Un correctif est en cours: https://github.com/python/cpython/pull/3027

82
hpaulj