web-dev-qa-db-fra.com

Comment créer un espace de noms Python (valeur argparse.parse_args))?

Pour tester interactivement mon script python, je voudrais créer un objet Namespace, similaire à ce qui serait retourné par argparse.parse_args(). La manière évidente,

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.parse_args()
Namespace()
>>> parser.parse_args("-a")
usage: [-h]
: error: unrecognized arguments: - a

Process Python exited abnormally with code 2

peut entraîner Python repl sortie (comme ci-dessus) sur une erreur idiote.

Donc, quel est le moyen le plus simple de créer un Python avec un ensemble d'attributs donné?

Par exemple, je peux créer un dict à la volée (dict([("a",1),("b","c")])) mais je ne peux pas l'utiliser comme Namespace:

AttributeError: 'dict' object has no attribute 'a'
40
sds

Vous pouvez créer une classe simple:

class Namespace:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

et cela fonctionnera exactement de la même manière que la classe argparseNamespace en ce qui concerne les attributs:

>>> args = Namespace(a=1, b='c')
>>> args.a
1
>>> args.b
'c'

Alternativement, il suffit d'importer la classe ; il est disponible depuis le module argparse:

from argparse import Namespace

args = Namespace(a=1, b='c')

Depuis Python 3.3, il y a aussi types.SimpleNamespace , qui fait essentiellement la même chose:

>>> from types import SimpleNamespace
>>> args = SimpleNamespace(a=1, b='c')
>>> args.a
1
>>> args.b
'c'

Les deux types sont distincts; SimpleNamespace est principalement utilisé pour l'attribut sys.implementation et la valeur de retour de time.get_clock_info().

Comparaisons supplémentaires:

  • Les deux classes prennent en charge les tests d'égalité; pour deux instances de la même classe, instance_a == instance_b est vrai si elles ont les mêmes attributs avec les mêmes valeurs.
  • Les deux classes ont un __repr__ Utile pour montrer leurs attributs.
  • Namespace() les objets prennent en charge les tests de confinement; 'attrname' in instance Est vrai si l'instance d'espace de noms a un attribut namend attrname. SimpleNamespace ne fonctionne pas.
  • Les objets Namespace() ont une méthode ._get_kwargs() non documentée qui retourne une liste triée d'attributs (name, value) pour cette instance. Vous pouvez obtenir la même chose pour chaque classe en utilisant sorted(vars(instance).items()).
  • Alors que SimpleNamespace() est implémenté en C et Namespace() est implémenté en Python, l'accès aux attributs n'est pas plus rapide car les deux utilisent le même stockage __dict__ Pour les attributs. Les tests d'égalité et la production de la représentation sont un peu plus rapides pour les instances SimpleNamespace().
84
Martijn Pieters

Il est désormais recommandé d'utiliser SimpleNamespace à partir du module types. Il fait la même chose que la réponse acceptée, sauf qu'il sera plus rapide et comportera quelques éléments supplémentaires tels que equals et repr.

from types import SimpleNamespace

sn = SimpleNamespace()
sn.a = 'test'
sn.a

# output
'test'
5
Mitchell Walls