Using argparse with parameters defined in config file
The use of a json file/expression as a source for defining argparse arguments is clever, and I think sound.  ipython defines many of its commandline arguments from values in a config file.

I commented that we need to be careful about what type does.  It's a frequent point of confusion.  It is a callable, usually a function, that takes a string, and converts it to the kind of value you want in the args namespace.  Its relation to builtin types and the the Python type function is only tangential.  

int and float work because those functions take a string and return a desired value (or raise an error).  bool does not because it does not take string and return a True/False (try bool('False').

argparse has an undocumentated registries mechanism that maps from strings to callables.  Mostly it is used for the action parameter, but can also be used with type.  Basically it's a dictionary.

Here's a quick session to illustrate its use.

In [2]: parser=argparse.ArgumentParser()


parser.register is an undocumented method, used internally, but available to the user (no _):

In [3]: parser.register?
Type:       instancemethod
...
File:       /usr/local/lib/python2.7/argparse.py
Definition: parser.register(self, registry_name, value, object)
Docstring:  &lt;no docstring&gt;


It sets an entry in a dictionary that the parser owns.  Notice all the familiar action values.  This maps from those strings to the Action subclasses.  There is only one type entry, the default case that does nothing (leaves a string unchanged).

In [4]: parser._registries
Out[4]: 
{'action': {None: argparse._StoreAction,
  'append': argparse._AppendAction,
  'append_const': argparse._AppendConstAction,
  'count': argparse._CountAction,
  'help': argparse._HelpAction,
  ...
 'type': {None: &lt;function argparse.identity&gt;}}


So let's add some entries to the register:

In [5]: parser.register('type','float',float)
In [6]: parser.register('type','int',int)
In [7]: parser.register('type','str',None)


and create some Actions to use them:

In [8]: parser.add_argument('-i',type='int')
....
In [9]: parser.add_argument('-f',type='float')
...
In [10]: parser.add_argument('-s',type='str')
... 
ValueError: None is not callable


Oops, it didn't like my None.  I was intending the None to map on to the existing None mapping in the registries, but it does not do that kind of double mapping.

I think the str() function will work.  It takes a string and returns it unchanged.  The argparse identity is more like a do nothing lambda x:x.

In [12]: str('astirng')
Out[12]: 'astirng'

In [13]: parser.register('type','str',str)

In [14]: parser.add_argument('-s',type='str')
Out[14]: _StoreAction(option_strings=['-s'], dest='s', nargs=None, const=None, default=None, type='str', choices=None, help=None, metavar=None)


Now let's test:

In [15]: parser.parse_args('-i 1 -f 23 -s 23'.split())
Out[15]: Namespace(f=23.0, i=1, s='23')


If you don't want to use register, I'd recommend a dictionary over eval.  As another answer notes there aren't that many types, and you have more control over the translation.

A recent SO question suggests on potential difficulty with your json-argparse mapping.  Not all Actions take a type parameter.  Your set of parameters is fine for the defaultstoreaction.  But astore_trueaction raises an error if you give it atype` parameter.

https://stackoverflow.com/questions/33574270/typeerror-init-got-an-unexpected-keyword-argument-type-in-argparse



I'd prefer calling add_argument with:

parser.add_argument(*args, **kwargs)


and build up args as a list, and kwargs as a dictionary. For example instead of :

for key, val in arguments.items():
    parser.add_argument('-%s' % key,
                        type=eval(val["type"]),
                        help=val["help"],
                        default=val["default"])


use something like:

for key, val in arguments.items():
    args = ['-%s'%key]
    kwargs = {&lt;some defaults&gt;}
    kwargs.update(val)
    parser.add_argument(*args, **kwargs)


This would allow me to use json strings like

'foo': {'action': 'store_true',
           'help': 'True/False values'},
   'bar': {'type': 'int',
           'default': 2},
   'baz': {'nargs': '+',
           'help': 'multiple values'}

I haven't tested this yet, but if I've got it right, it would give more flexibility.  Internally argparse uses **kwargs a lot to handle the large numbers of parameters that its methods take.