Mittenchops
Mittenchops

Reputation: 19664

Python argparse parse_args into global namespace (or a reason this is a bad idea)

I've mostly used argparse for making command-line scripts in python, and the idiom I generally use is that I assign the arguments as attributes of an object, then parse them individually to a variable that matches their attribute name. This seems a little repetitive. Is there a way to assign them all into the global namespace and cut out the assignment step; or as is often the case when some python behavior seems counter-intuitive to me, can some wise, python expert point out that there a good reason I should not do this or want to do this?

What I have now is this:

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--db",type=str, dest='db', nargs='?', default="test")
    parser.add_argument("--collection",type=str, dest='collection', nargs='?', help="Collection, default is test", default="test")
    args = parser.parse_args()
    db = args.db                   # gross! 
    collection = args.collection   # yuck!
    print(db)
    print(collection)

What I'd like this is:

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--db",type=str, dest='db', nargs='?', default="test")
    parser.add_argument("--collection",type=str, dest='collection', nargs='?', help="Collection, default is test", default="test")
    parser.SUPER_parse_args() # now, db and collection are already in the namespace!
    print(db)
    print(collection)

It doesn't seem like much when I only have 2 arguments, but if I have 10 or so, doubling the assign steps, where I rename into the global namespace the attributes that already exist in the args object, starts to bug me.

Upvotes: 11

Views: 14483

Answers (3)

Zhanwen Chen
Zhanwen Chen

Reputation: 1463

This is what I did. It helps with variable collision but not maintainability.

parser_args = parser.parse_args()
if parser_args.verbose:
    globals().update(argparse.Namespace(verbose=parser_args.verbose).__dict__)

Upvotes: 0

Joe
Joe

Reputation: 11

To add onto mgilson's answer:

Consider using locals().update(args.__dict__) instead; this will update the current namespace rather than the global namespace.

You can also do this using locals() or vars(). See this Stack Overflow post for a nice explanation on the difference between the two.

I'm a bit late for Mittonchops, but hopefully this helps others.

Upvotes: 0

mgilson
mgilson

Reputation: 309929

You can do this using globals:

globals().update(args.__dict__)

however, you really *shouldn't do that. From the zen of python,

Namespaces are one honking great idea -- let's do more of those!

I'll echo what @Martijn said in his comment:

Don't. Just don't. I'd use args directly instead.

Keep things as nicely separated as you can. It makes for more maintainable and easier to understand code.

Upvotes: 11

Related Questions