如何创建 Python 名称空间(argparse.parse_args 值) ?

为了交互式地测试我的 python 脚本,我想创建一个 Namespace对象,类似于 argparse.parse_args()返回的对象。 很明显,

>>> 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

可能导致 Python repl 在一个愚蠢的错误上退出(如上所述)。

那么,创建具有给定属性集的 Python 名称空间的最简单方法是什么?

例如,我可以在运行中创建一个 dict(dict([("a",1),("b","c")])) ,但是我不能将它用作 Namespace:

AttributeError: 'dict' object has no attribute 'a'
72687 次浏览

You can create a simple class:

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

and it'll work the exact same way as the argparse Namespace class when it comes to attributes:

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

Alternatively, just import the class; it is available from the argparse module:

from argparse import Namespace


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

As of Python 3.3, there is also types.SimpleNamespace, which essentially does the same thing:

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

The two types are distinct; SimpleNamespace is primarily used for the sys.implementation attribute and the return value of time.get_clock_info().

Further comparisons:

  • Both classes support equality testing; for two instances of the same class, instance_a == instance_b is true if they have the same attributes with the same values.
  • Both classes have a helpful __repr__ to show what attributes they have.
  • Namespace() objects support containment testing; 'attrname' in instance is true if the namespace instance has an attribute namend attrname. SimpleNamespace does not.
  • Namespace() objects have an undocumented ._get_kwargs() method that returns a sorted list of (name, value) attributes for that instance. You can get the same for either class using sorted(vars(instance).items()).
  • While SimpleNamespace() is implemented in C and Namespace() is implemented in Python, attribute access is no faster because both use the same __dict__ storage for the attributes. Equality testing and producing the representation are a little faster for SimpleNamespace() instances.

argparse documentation show various examples of what you're trying to do:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-a")
parser.parse_args(['-a 12'])
>>> Namespace(a=' 12')

It is now recommended to use SimpleNamespace from the types module. It does the same thing as the accepted answer except for it will be faster and have a few more builtins such as equals and repr.

from types import SimpleNamespace


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


# output
'test'

First create a dict and then use the dict to create an namespace:

from argparse import Namespace
x = {'a': 1, 'b': 2}
ns = Namespace(**x)
print(ns.a) #output 1