Issue 32668: deepcopy() fails on ArgumentParser instances (original) (raw)
We (the Anaconda OS intaller team) are in the process of switching to a new version of a library (Pykickstart), which among other things switched from using optparse to argparse. And during this endeavour we found that it's apparently not possible to deepcopy ArgumentParser instances:
$ ipython3 Python 3.6.3 (default, Oct 9 2017, 12:07:10) Type 'copyright', 'credits' or 'license' for more information IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import argparse
In [2]: from copy import deepcopy
In [3]: parser = argparse.ArgumentParser()
In [4]: deepcopy(parser)
TypeError Traceback (most recent call last) in () ----> 1 deepcopy(parser)
/usr/lib64/python3.6/copy.py in deepcopy(x, memo, _nil) 178 y = x 179 else: --> 180 y = _reconstruct(x, memo, *rv) 181 182 # If is its own copy, don't memoize.
/usr/lib64/python3.6/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy) 278 if state is not None: 279 if deep: --> 280 state = deepcopy(state, memo) 281 if hasattr(y, 'setstate'): 282 y.setstate(state)
/usr/lib64/python3.6/copy.py in deepcopy(x, memo, _nil) 148 copier = _deepcopy_dispatch.get(cls) 149 if copier: --> 150 y = copier(x, memo) 151 else: 152 try:
/usr/lib64/python3.6/copy.py in _deepcopy_dict(x, memo, deepcopy) 238 memo[id(x)] = y 239 for key, value in x.items(): --> 240 y[deepcopy(key, memo)] = deepcopy(value, memo) 241 return y 242 d[dict] = _deepcopy_dict
/usr/lib64/python3.6/copy.py in deepcopy(x, memo, _nil) 148 copier = _deepcopy_dispatch.get(cls) 149 if copier: --> 150 y = copier(x, memo) 151 else: 152 try:
/usr/lib64/python3.6/copy.py in _deepcopy_list(x, memo, deepcopy) 213 append = y.append 214 for a in x: --> 215 append(deepcopy(a, memo)) 216 return y 217 d[list] = _deepcopy_list
/usr/lib64/python3.6/copy.py in deepcopy(x, memo, _nil) 178 y = x 179 else: --> 180 y = _reconstruct(x, memo, *rv) 181 182 # If is its own copy, don't memoize.
/usr/lib64/python3.6/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy) 278 if state is not None: 279 if deep: --> 280 state = deepcopy(state, memo) 281 if hasattr(y, 'setstate'): 282 y.setstate(state)
/usr/lib64/python3.6/copy.py in deepcopy(x, memo, _nil) 148 copier = _deepcopy_dispatch.get(cls) 149 if copier: --> 150 y = copier(x, memo) 151 else: 152 try:
/usr/lib64/python3.6/copy.py in _deepcopy_dict(x, memo, deepcopy) 238 memo[id(x)] = y 239 for key, value in x.items(): --> 240 y[deepcopy(key, memo)] = deepcopy(value, memo) 241 return y 242 d[dict] = _deepcopy_dict
/usr/lib64/python3.6/copy.py in deepcopy(x, memo, _nil) 178 y = x 179 else: --> 180 y = _reconstruct(x, memo, *rv) 181 182 # If is its own copy, don't memoize.
/usr/lib64/python3.6/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy) 278 if state is not None: 279 if deep: --> 280 state = deepcopy(state, memo) 281 if hasattr(y, 'setstate'): 282 y.setstate(state)
/usr/lib64/python3.6/copy.py in deepcopy(x, memo, _nil) 148 copier = _deepcopy_dispatch.get(cls) 149 if copier: --> 150 y = copier(x, memo) 151 else: 152 try:
/usr/lib64/python3.6/copy.py in _deepcopy_dict(x, memo, deepcopy) 238 memo[id(x)] = y 239 for key, value in x.items(): --> 240 y[deepcopy(key, memo)] = deepcopy(value, memo) 241 return y 242 d[dict] = _deepcopy_dict
/usr/lib64/python3.6/copy.py in deepcopy(x, memo, _nil) 159 copier = getattr(x, "deepcopy", None) 160 if copier: --> 161 y = copier(memo) 162 else: 163 reductor = dispatch_table.get(cls)
TypeError: cannot deepcopy this pattern object
This should either be fixed or documented in proper places (the argparse documentation does not mention any pottential deepcopy issues as far as we can tell).
Hi, you seem to be in luck, regardless of version.
Python 3.7.0a4+ (heads/master:a49ac99029, Jan 27 2018, 00:11:50) [MSC v.1900 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information.
import argparse from copy import deepcopy parser = argparse.ArgumentParser() deepcopy(parser) ArgumentParser(prog='', usage=None, description=None, formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True)
Fresh 3.6.4+ build also runs, but without enhanced repr. ... <class 'argparse.ArgumentParser'>
(Note: 'crash' here means segfault rather than Python exception.)