Est-il possible de supprimer ou de désactiver un argument dans argparse, de sorte qu'il n'apparaisse pas dans l'aide? Comment?
Il est facile d'ajouter de nouveaux arguments:
parser = argparse.ArgumentParser()
parser.add_argument('--arg1', help='Argument 1')
parser.add_argument('--arg2', help='A second one')
Et je sais que vous pouvez remplacer les arguments par une nouvelle définition en spécifiant le gestionnaire de conflit "résoudre":
#In one script that should stand-alone and include arg1:
parser = argparse.ArgumentParser(conflict_handler='resolve')
parser.add_argument('--arg1', help='Argument 1')
parser.add_argument('--arg2', help='A second one')
#In another script with similar options
parser.add_argument('--arg1', help='New number 1')
Mais cela inclut toujours arg1 dans le message d’aide et les résultats de parse_args
Y at-il quelque chose comme:
#Wishful thinking
#In another script with similar options, that shouldn't include arg1
parser.remove_argument('--arg1')
Ou un autre moyen raisonnablement facile d'y parvenir?
Aussi: l'approche serait-elle différente si l'argument était un argument de position?
Remarque: le problème avec la suppression de arg1
après l'analyse comme suggéré ici est que l'argument est toujours affiché dans l'aide.
Malgré le problème de bogue que je mentionne ci-dessous, votre utilisation de resolve
suggère une méthode possible. Ce n'est pas pour le novice ou quelqu'un qui a besoin de s'en tenir à l'API publique.
La parser
a une liste des objets Action (argument) (créés par add_argument
).
En utilisant votre deuxième définition d’analyseur, sa liste _actions
est:
In [22]: parser._actions
Out[22]:
[_HelpAction(option_strings=['-h', '--help'], dest='help'...),
_StoreAction(option_strings=['--arg2'], dest='arg2', nargs=None,
const=None, default=None, type=None, choices=None,
help='A second one', metavar=None),
_StoreAction(option_strings=['--arg1'], dest='arg1', nargs=None,
const=None, default=None, type=None, choices=None,
help='New number 1', metavar=None)]
Lorsque vous ajoutez une conflit avec resolve
, l'action existante en conflit est supprimée. Regardez la méthode _handle_conflict_resolve
pour plus de détails. Mais je peux le tromper en supprimant une action sans en ajouter une nouvelle.
In [23]: parser._handle_conflict_resolve(None, [('--arg1',parser._actions[2])])
Examinez _actions
et aidez-nous à vérifier que --arg1
est parti.
In [24]: parser._actions
Out[24]:
[_HelpAction(option_strings=['-h', '--help'], dest='help',....),
_StoreAction(option_strings=['--arg2'], dest='arg2', nargs=None,...)]
In [25]: parser.print_help()
usage: ipython3 [-h] [--arg2 ARG2]
optional arguments:
-h, --help show this help message and exit
--arg2 ARG2 A second one
resolve
gère simplement optionals
, ceux où les chaînes de drapeau peuvent entrer en conflit. Et il supprime d'abord les indicateurs en conflit, en supprimant l'action en conflit uniquement s'il ne reste aucun indicateur. Faites donc très attention lorsque vous avez les options courtes et longues.
Et cela ne concerne pas le cas des positions. Ils n'ont pas d'indicateur et peuvent partager des paramètres dest
. (bien qu'un seul apparaisse dans le résultat, à moins qu'il s'agisse d'actions ajoutées).
In [27]: foo1 = parser.add_argument('foo',help='foo 1 positional')
In [28]: foo2 = parser.add_argument('foo',help='foo 2 positional')
In [29]: parser.print_help()
usage: ipython3 [-h] [--arg2 ARG2] foo foo
positional arguments:
foo foo 1 positional
foo foo 2 positional
...
En jouant un peu plus, il semble que je puisse supprimer l'un de ces nouveaux positionnels:
In [33]: parser._actions[-1]
Out[33]: _StoreAction(option_strings=[], dest='foo',... help='foo 2 positional', metavar=None)
In [35]: foo2=parser._actions[-1]
In [36]: foo2.container._remove_action(foo2)
In [39]: parser.print_help()
usage: ipython3 [-h] [--arg2 ARG2] foo
positional arguments:
foo foo 1 positional
....
Si j'avais choisi _actions[-2]
, j'aurais supprimé la première foo
. Si j’assigne la valeur que add_argument
renvoie à une variable, par ex. foo1
, je peux l'utiliser au lieu de rechercher la valeur dans la liste parser._actions
. Il peut être utile d'exécuter un exemple d'analyse dans un shell interactif (j'utilise IPython) et d'examiner ces objets.
Là encore, cela semble fonctionner sur un exemple simple, mais il nécessite des tests minutieux s'il est utilisé avec quelque chose de plus complexe (ou pour la production).
Le sujet a été abordé sur les problèmes/problèmes de Python il y a quelques années:
http://bugs.python.org/issue19462Add remove_argument() method to argparse.ArgumentParser
J'ai discuté des difficultés d'élimination complète et suggéré quelques alternatives. argparse.SUPPRESS
peut être utilisé pour masquer des aides. optionals
peut être ignoré s’ils ne sont pas obligatoires. positionals
sont plus compliqués, bien que j’ai suggéré de modifier leurs attributs (nargs
et default
). Mais cela fait longtemps, je dois donc passer en revue ces publications.
=============================
J'étais curieux de connaître le problème @2rs2ts
(voir le commentaire).
J'ai créé un analyseur, puis je l'ai utilisé comme parent d'un autre analyseur (inutile d'utiliser le mécanisme subparser). Ensuite, j'ai enlevé un argument d'un analyseur et j'ai examiné les modifications apportées à l'autre analyseur.
Créez un analyseur parent avec un argument:
In [59]: p=argparse.ArgumentParser()
In [60]: p.add_argument('--foo')
Out[60]: _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
Faites un autre avec parents
:
In [61]: p1=argparse.ArgumentParser(parents=[p],add_help=False)
In [62]: p1._actions
Out[62]:
[_HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None),
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)]
Notez que la 2ème action est la même pour les deux analyseurs (même id). parents
vient de copier une référence à l'action --foo
d'origine, elle n'a pas été copiée.
In [63]: id(p._actions[1])
Out[63]: 3000108652
In [64]: id(p1._actions[1])
Out[64]: 3000108652
Supprimez maintenant '--foo' d'un analyseur, en utilisant le truc que j'ai développé précédemment:
In [65]: p1._handle_conflict_resolve(None,[('--foo',p1._actions[1])])
In [66]: p1._actions
Out[66]: [_HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None)]
'--foo' n'est plus dans la liste p1
, mais est toujours présent dans la liste p
. Mais option_strings
est maintenant vide.
In [67]: p._actions
Out[67]:
[_HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None),
_StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)]
Le code resolve
a supprimé le option_strings
en conflit de l'action --foo
, puis l'a supprimé de la liste p1._actions
. Mais changer option_strings
pour la référence p1
a également changé la référence p
.
argparse
utilise deux méthodes pour distinguer positionals
de optionals
, mais celle utilisée le plus souvent dans l'analyse consiste à déterminer si l'attribut option_strings
est vide ou non. En vidant cet attribut, resolve
a effectivement transformé une optional
en une positional
.
Oups, ma mémoire n'est pas ce qu'elle devrait être. :) Il y a un an, j'ai répondu à une question similaire concernant parents
et resolve
https://stackoverflow.com/a/25821043/901925argparse conflict resolver for options in subcommands turns keyword argument into positional argument
Est-il possible de supprimer ou de désactiver un argument dans argparse, tel que N'apparaisse pas dans l'aide?
Définissez help
sur argparse.SUPPRESS
lorsque vous ajoutez l'argument, comme ceci:
parser.add_argument('--arg1', help=argparse.SUPPRESS)
Cela empêchera l'argument d'apparaître dans la sortie d'aide par défaut.
Fonction pour supprimer les options argparse:
def remove_options(parser, options):
for option in options:
for action in parser._actions:
if vars(action)['option_strings'][0] == option:
parser._handle_conflict_resolve(None,[(option,action)])
break
Bien que la réponse de hpaulj soit excellente, dans mon cas, utiliser simplement parser._remove_action(action)
ne supprimait pas les "arguments de position" pour aider l'action supprimée. Ma solution de contournement consistait à le supprimer également du _action_group
def remove_option(parser, arg):
for action in parser._actions:
if (vars(action)['option_strings']
and vars(action)['option_strings'][0] == arg) \
or vars(action)['dest'] == arg:
parser._remove_action(action)
for action in parser._action_groups:
vars_action = vars(action)
var_group_actions = vars_action['_group_actions']
for x in var_group_actions:
if x.dest == arg:
var_group_actions.remove(x)
return