'Can't pickle local object 'ArgumentParser.__init__.<locals>.identity

import argparse
import pickle

parser = argparse.ArgumentParser(description='Process some integers.')
_ = pickle.dumps(parser)

In my code, the ArgumentParser object is serialized. But in runtime I get the error Can't pickle local object 'ArgumentParser.__init__.<locals>.identity. In Lib/argparse.py the identity is function defined locally inside __init__ method and this prevents serialization. If convert this function to a method, then serialization is successful. But I think that this way is not the best solution, since the python library file is being changed. How serialize parser object best way?



Solution 1:[1]

I had a program that used sub-parsers and initializing the ArgumentParser noticeably delayed startup, even for —help. I experimented with several things encountered this. I found this to work.

from argparse import ArgumentParser
from pickle import dumps

def identity(string):
    return string

p = ArgumentParser()
p.register('type', None, identity)
x = dumps(p)

Solution 2:[2]

I created the heir class class ArgumentParserSerializable(ArgumentParser) and definied identity method as static. It also works.

class ArgumentParserSerializable(ArgumentParser):

def __init__(self,
             prog=None,
             usage=None,
             description=None,
             epilog=None,
             parents=[],
             formatter_class=HelpFormatter,
             prefix_chars='-',
             fromfile_prefix_chars=None,
             argument_default=None,
             conflict_handler='error',
             add_help=True,
             allow_abbrev=True):

    superinit = super(ArgumentParser, self).__init__
    superinit(description=description,
              prefix_chars=prefix_chars,
              argument_default=argument_default,
              conflict_handler=conflict_handler)

    # default setting for prog
    if prog is None:
        prog = _os.path.basename(_sys.argv[0])

    self.prog = prog
    self.usage = usage
    self.epilog = epilog
    self.formatter_class = formatter_class
    self.fromfile_prefix_chars = fromfile_prefix_chars
    self.add_help = add_help
    self.allow_abbrev = allow_abbrev

    add_group = self.add_argument_group
    self._positionals = add_group(_('positional arguments'))
    self._optionals = add_group(_('optional arguments'))
    self._subparsers = None

    self.register('type', None, self.identity)

    # add help argument if necessary
    # (using explicit default to override global argument_default)
    default_prefix = '-' if '-' in prefix_chars else prefix_chars[0]
    if self.add_help:
        self.add_argument(
            default_prefix + 'h', default_prefix * 2 + 'help',
            action='help', default=SUPPRESS,
            help=_('show this help message and exit'))

    # add parent arguments and defaults
    for parent in parents:
        self._add_container_actions(parent)
        try:
            defaults = parent._defaults
        except AttributeError:
            pass
        else:
            self._defaults.update(defaults)

# register types
@staticmethod
def identity(string):
    return string

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 samwyse
Solution 2 Tarletsky Andrey