2

Let's say I have an args namespace after parsing my command line with argparse. Now, I want to use this to create some objects like this:

foo = Foo(bar=args.bar)

Unfortunately, I have the restriction that if a keyword argument is set, it must not be None. Now, I need to check if args.bar is set and act accordingly:

if args.bar:
    foo = Foo(bar=args.bar)
else:
    foo = Foo()

This is unwieldy and doesn't scale for more arguments. What I'd like to have, is something like this:

foo = Foo(**args.__dict__)

but this still suffers from my initial problem and additionally doesn't work for keys that are not keyword arguments of the __init__ method. Is there a good way to achieve these things?

matthias
  • 2,161
  • 15
  • 22

2 Answers2

3

You could try something like this:

>>> defined_args = {k:v for k,v in args._get_kwargs() if v is not None}
>>> foo = Foo(**defined_args)

For example:

>>> import argparse
>>> args = argparse.Namespace(key1=None,key2='value')
>>> {k:v for k,v in args._get_kwargs() if v is not None}
{'key2': 'value'}

Note, however, that _get_kwargs() is not part of the public API so may or may not be available in future releases/versions.

isedev
  • 18,848
  • 3
  • 60
  • 59
  • what's the difference between `args._get_kwargs` and `args.__dict__`? – mgilson Mar 01 '13 at 15:47
  • @mgilson -- you made me check: none really :) `def _get_kwargs(self): return sorted(self.__dict__.items())`. But I suppose if the module maintainer ever added non-keyword attributes to `_AttributeHolder`, the base class of `Namespace`, he/she/they would presumably exclude them from `_get_kwargs`. – isedev Mar 01 '13 at 15:48
  • In that case, maybe you should just use `args.__dict__.items()`. `args.__dict__` is guaranteed to exist (since there is no way a `Namespace` can know what arguments it will have ahead of time, it can't implement `__slots__` as far as I can see). And, I suppose, if you're really paranoid, you could subclass `Namespace` and pass that into `parse_args` too... – mgilson Mar 01 '13 at 15:51
3

I think you can use vars():

args = parser.parse_args()
Foo(**vars(args))

vars([object]) returns the namespace as a dictionary

ypnos
  • 50,202
  • 14
  • 95
  • 141