How do I create a Python namespace (argparse.parse_args value)?
Question:
To interactively test my python script, I would like to create a Namespace
object, similar to what would be returned by argparse.parse_args()
.
The obvious way,
>>> 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
may result in Python repl exiting (as above) on a silly error.
So, what is the easiest way to create a Python namespace with a given set of attributes?
E.g., I can create a dict
on the fly (dict([("a",1),("b","c")])
) but I cannot use it as a Namespace
:
AttributeError: 'dict' object has no attribute 'a'
Answers:
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
To interactively test my python script, I would like to create a Namespace
object, similar to what would be returned by argparse.parse_args()
.
The obvious way,
>>> 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
may result in Python repl exiting (as above) on a silly error.
So, what is the easiest way to create a Python namespace with a given set of attributes?
E.g., I can create a dict
on the fly (dict([("a",1),("b","c")])
) but I cannot use it as a Namespace
:
AttributeError: 'dict' object has no attribute 'a'
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 namendattrname
.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 usingsorted(vars(instance).items())
.- While
SimpleNamespace()
is implemented in C andNamespace()
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 forSimpleNamespace()
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