How to iterate over arguments
Question:
I have such script:
import argparse
parser = argparse.ArgumentParser(
description='Text file conversion.'
)
parser.add_argument("inputfile", help="file to process", type=str)
parser.add_argument("-o", "--out", default="output.txt",
help="output name")
parser.add_argument("-t", "--type", default="detailed",
help="Type of processing")
args = parser.parse_args()
for arg in args:
print(arg)
But it doesnt work. I get error:
TypeError: 'Namespace' object is not iterable
How to iterate over arguments and their value?
Answers:
Namespace
objects aren’t iterable, the standard docs suggest doing the following if you want a dictionary:
>>> vars(args)
{'foo': 'BAR'}
So
for key, value in vars(args).items():
# do stuff
To be honest, I am not sure why you want to iterate over the arguments. That somewhat defeats the purpose of having an argument parser.
Add vars
if you want to iterate over a Namespace
object:
for arg in vars(args):
print arg, getattr(args, arg)
ArgumentParser.parse_args
returns a Namespace
object instead of an iterable arrays.
For your reference, https://docs.python.org/3/library/argparse.html#parsing-arguments
ArgumentParser parses arguments through the parse_args() method. This will inspect the command line, convert each argument to the appropriate type and then invoke the appropriate action.
And it is not supposed to be used like that. Consider your use case, in the doc, it says argparse
will figure out how to parse those out of sys.argv
., which means you don’t have to iterate over those arguments.
After
args = parser.parse_args()
to display the arguments, use:
print args # or print(args) in python3
The args
object (of type argparse.Namespace
) isn’t iterable (i.e. not a list), but it has a .__str__
method, which displays the values nicely.
args.out
and args.type
give the values of the 2 arguments you defined. This works most of the time. getattr(args, key)
the most general way of accessing the values, but usually isn’t needed.
vars(args)
turns the namespace into a dictionary, which you can access with all the dictionary methods. This is spelled out in the docs
.
ref: the Namespace paragraph of the docs – https://docs.python.org/2/library/argparse.html#the-namespace-object
I’m using args.__dict__
, which lets you access the underlying dict structure.
Then, its a simple key-value iteration:
for k in args.__dict__:
print k, args.__dict__[k]
Parsing the _actions from your parser seems like a decent idea. Instead of running parse_args() and then trying to pick stuff out of your Namespace.
import argparse
parser = argparse.ArgumentParser(
description='Text file conversion.')
parser.add_argument("inputfile", help="file to process", type=str)
parser.add_argument("-o", "--out", default="output.txt",
help="output name")
parser.add_argument("-t", "--type", default="detailed",
help="Type of processing")
options = parser._actions
for k in options:
print(getattr(k, 'dest'), getattr(k, 'default'))
You can modify the ‘dest’ part to be ‘choices’ for example if you need the preset defaults for a parameter in another script (by returning the options in a function for example).
Using the builtin dict()
class to iterate over the args is straightforward and works great:
args = parser.parse_args()
args_dict = dict(vars(args))
for i, ii in args_dict.items():
print(i, ii)
From builtins.py
:
def __init__(self, seq=None, **kwargs): # known special case of dict.__init__
"""
dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
d = {}
for k, v in iterable:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
# (copied from class doc)
"""
pass
I have such script:
import argparse
parser = argparse.ArgumentParser(
description='Text file conversion.'
)
parser.add_argument("inputfile", help="file to process", type=str)
parser.add_argument("-o", "--out", default="output.txt",
help="output name")
parser.add_argument("-t", "--type", default="detailed",
help="Type of processing")
args = parser.parse_args()
for arg in args:
print(arg)
But it doesnt work. I get error:
TypeError: 'Namespace' object is not iterable
How to iterate over arguments and their value?
Namespace
objects aren’t iterable, the standard docs suggest doing the following if you want a dictionary:
>>> vars(args)
{'foo': 'BAR'}
So
for key, value in vars(args).items():
# do stuff
To be honest, I am not sure why you want to iterate over the arguments. That somewhat defeats the purpose of having an argument parser.
Add vars
if you want to iterate over a Namespace
object:
for arg in vars(args):
print arg, getattr(args, arg)
ArgumentParser.parse_args
returns a Namespace
object instead of an iterable arrays.
For your reference, https://docs.python.org/3/library/argparse.html#parsing-arguments
ArgumentParser parses arguments through the parse_args() method. This will inspect the command line, convert each argument to the appropriate type and then invoke the appropriate action.
And it is not supposed to be used like that. Consider your use case, in the doc, it says argparse
will figure out how to parse those out of sys.argv
., which means you don’t have to iterate over those arguments.
After
args = parser.parse_args()
to display the arguments, use:
print args # or print(args) in python3
The args
object (of type argparse.Namespace
) isn’t iterable (i.e. not a list), but it has a .__str__
method, which displays the values nicely.
args.out
and args.type
give the values of the 2 arguments you defined. This works most of the time. getattr(args, key)
the most general way of accessing the values, but usually isn’t needed.
vars(args)
turns the namespace into a dictionary, which you can access with all the dictionary methods. This is spelled out in the docs
.
ref: the Namespace paragraph of the docs – https://docs.python.org/2/library/argparse.html#the-namespace-object
I’m using args.__dict__
, which lets you access the underlying dict structure.
Then, its a simple key-value iteration:
for k in args.__dict__:
print k, args.__dict__[k]
Parsing the _actions from your parser seems like a decent idea. Instead of running parse_args() and then trying to pick stuff out of your Namespace.
import argparse
parser = argparse.ArgumentParser(
description='Text file conversion.')
parser.add_argument("inputfile", help="file to process", type=str)
parser.add_argument("-o", "--out", default="output.txt",
help="output name")
parser.add_argument("-t", "--type", default="detailed",
help="Type of processing")
options = parser._actions
for k in options:
print(getattr(k, 'dest'), getattr(k, 'default'))
You can modify the ‘dest’ part to be ‘choices’ for example if you need the preset defaults for a parameter in another script (by returning the options in a function for example).
Using the builtin dict()
class to iterate over the args is straightforward and works great:
args = parser.parse_args()
args_dict = dict(vars(args))
for i, ii in args_dict.items():
print(i, ii)
From builtins.py
:
def __init__(self, seq=None, **kwargs): # known special case of dict.__init__
"""
dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
d = {}
for k, v in iterable:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
# (copied from class doc)
"""
pass