Reputation: 429
I am currently writing a Python script and trying to dynamically generate some arguments. However, an error is being thrown for the following script, stating 'Namespace' object is not iterable.
Any ideas on how to fix?
import argparse
from os import path
import re
replacements = {}
pattern = '<<([^>]*)>>'
def user_replace(match):
## Pull from replacements dict or prompt
placeholder = match.group(1)
return (replacements[placeholder][0]
if placeholder in replacements else
raw_input('%s? ' % placeholder))
def main():
parser = argparse.ArgumentParser()
parser.add_argument('infile', type=argparse.FileType('r'))
parser.add_argument('outfile', type=argparse.FileType('w'))
required, extra = parser.parse_known_args()
infile, outfile = required.infile, required.outfile
args = re.findall(pattern, infile.read())
args = list(set(args))
infile.seek(0)
parser = argparse.ArgumentParser()
for arg in args:
parser.add_argument('--' + arg.lower())
replacements = vars(parser.parse_args(extra))
matcher = re.compile(pattern)
for line in args.infile:
new_line = matcher.sub(user_replace, line)
args.outfile.write(new_line)
args.infile.close()
args.outfile.close()
if __name__ == '__main__':
main()
The error is with the returned value of parser.parse_known_args(). Any ideas on how I could bypass this though? Someone suggested creating an object and using the dict interface, but I don't know what this entails exactly. I'm really new to Python, so I don't understand why (infile, outfile), extra = parser.parse_known_args() wouldn't work.
Edit: Updated with two fixes. First fixed the error above by using the accepted answer below. Second, also fixed an error where I was getting flagged for trying to add the same argument twice. Fixed by making args a set then back to a list. Now my script runs, but the optional arguments have no effect. Any ideas?
Upvotes: 9
Views: 25045
Reputation: 2390
I had a similar problem with the parse_args() method. I wanted to use the namespace as a dictionary. Since it looks like a dict, it should be possible!
args = parser.parse_args()
for k, v in args: -> "'Namespace' object is not iterable."
for k, v in dict(args): -> "'Namespace' object is not iterable."
for k, v in args.__dict__.iteritems():
print(k, v) # Works!
# Or just use it as any other dictionary
d.update(args.__dict__)
f(**args.__dict__)
Upvotes: 5
Reputation: 17
Actually, that line of code should read as follows:
namespace= parser.parse_known_args()
Otherwise, one still gets the error about namespaces not being iterable.
Upvotes: 0
Reputation: 65854
ArgumentParser.parse_known_args
returns a namespace and a list of the remaining arguments. Namespaces aren't iterable, so when you try to assign one to the tuple (infile, outfile)
you get the "not iterable" error.
Instead, you should write something like
namespace, extra = parser.parse_known_args()
and then access the parsed arguments as namespace.infile
and namespace.outfile
.
Upvotes: 20