Argparse - Custom Action update to an dest dict
<p>I want to collect some options as a dict using <code>argparse</code>. I have wrote a custom Action class as follows. The problem is that the <code>__call__</code> method is never invoked. </p>

<pre><code>#!/usr/bin/env python3

import argparse

class UpdateDict(argparse.Action):
    def __init__(self, option_strings, dest, nargs=None, **kwargs):
        print('UpdateDict', option_strings, dest, nargs)
        if nargs != 1:
            raise ValueError("nargs must be 1")
        super(UpdateDict, self).__init__(option_strings, dest, nargs=nargs, **kwargs)
        print(self)

    def __call__(self, parser, namespace, values, option_string=None):
        print('%r %r %r' % (namespace, values, option_string))
        dest = getattr(namespace, self.dest)
        print(dest)
        key = option_string[1]
        dest.update(key = values[0])

def parse_args():
    parser = argparse.ArgumentParser(description='formula alpha')
    parser.add_argument('formula', nargs=1, type=str, help='alpha formula')
    parser.set_defaults(mydict={})

    parser.add_argument('-a', '--alpha', nargs=1, type=str, default=['alas'], action=UpdateDict, dest='mydict')
    parser.add_argument('-b', '--beta', nargs=1, type=int, default=[0], action=UpdateDict, dest='mydict')

if __name__ == '__main__':                                                                                                                                                                                        
    args = parse_args()
    print(args)
</code></pre>

<p>Your <code>parse_args</code> function need to return the parser which it creates, as you need its <code>parse_args</code> method for the actual parsing.  Also, you should source the arguments from <code>sys.argv[1:]</code>, basically the arguments except for the main program's argument (i.e. your script name).  So you should rename <code>parse_args</code> to a more appropriate name.  An incomplete example:</p>

<pre><code>def make_parser():
    # your ArgumentParser construction code ...
    return parser

if __name__ == '__main__':
    import sys
    parser = make_parser()
    parser.parse_args(sys.argv[1:])
</code></pre>

<p>Do note that you have some minor issues with your implementation of your Action which you will need to fix.  When I threw all your code (with the <code>return parser</code> added) on the <code>ArgumentParser</code> that your code constructed, this was the issue:</p>

<pre><code>&gt;&gt;&gt; parser.parse_known_args(['-b', '1'])
Namespace(formula=None, mydict=['alas']) [1] '-b'
['alas']
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
  File "/usr/lib/python3.4/argparse.py", line 1769, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/usr/lib/python3.4/argparse.py", line 1975, in _parse_known_args
    start_index = consume_optional(start_index)
  File "/usr/lib/python3.4/argparse.py", line 1915, in consume_optional
    take_action(action, args, option_string)
  File "/usr/lib/python3.4/argparse.py", line 1843, in take_action
    action(self, namespace, argument_values, option_string)
  File "&lt;stdin&gt;", line 13, in __call__
AttributeError: 'list' object has no attribute 'update'
</code></pre>

python argparse