Open 6f7117d2-587d-4aa8-8861-178ebfcbf9a6 opened 3 years ago
copy.deepcopy()-ing a tree structure that has internal parent and cross-reference links implemented as weakref.proxy() objects causes the weak reference proxies themselves to be copied (still refering to their original referents) rather than weak references to deep-copied referents to be created.
A workaround is to add the following __deepcopy method to affected classes: def __deepcopy (self, memo): # taken from Stackoverflow: "How to override the # copy deepcopy operations for a python object" # and "Python: dereferencing weakproxy" cls = self.__class result = cls.__new (cls) memo [id (self)] = result for k, v in self.__dict.items (): if isinstance (v, weakref.ProxyType): newv = weakref.proxy (copy.deepcopy ( v.\_repr.__self__, memo)) else: new_v = copy.deepcopy (v, memo) setattr (result, k, new_v) return result
If you deep-copy the referents, what would hold a reference to them? Wouldn't the new objects be immediately GCed?
Well, in the example code, the memo dictionary contains the (hard) reference to newly created objects but ultimately, at the close of the deepcopy, the objects are (hard) referenced using the normal "child" attributes.
I don't however know how this would work if this was implemented within the weakref code but I expect that their __deepcopy__ method also has access to the memo variable. If, at the close of deepcopy and the destruction of memo, no (hard) references exist to an object, then it would be collected, but that matches standard weak reference semantics.
Even if it were not possible to solve this programmatically within Python, I think the problem (and e.g. the workaround given below) should be mentioned in the documentation of deepcopy and/or weakref.
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields: ```python assignee = None closed_at = None created_at =
labels = ['type-bug', 'library', '3.9']
title = 'deepcopy of weakref proxies'
updated_at =
user = 'https://github.com/konrad-schwarz'
```
bugs.python.org fields:
```python
activity =
actor = 'konrad.schwarz'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation =
creator = 'konrad.schwarz'
dependencies = []
files = []
hgrepos = []
issue_num = 43252
keywords = []
message_count = 3.0
messages = ['387226', '391094', '391121']
nosy_count = 2.0
nosy_names = ['iritkatriel', 'konrad.schwarz']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue43252'
versions = ['Python 3.9']
```