-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
Pickle handle self references in classes #82951
New issue
Have a question about this project? Sign up for a free GitHub account to open an iss 8000 ue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
If the __qualname__ of a class is set to have a circular reference to itself, pickle behaves differently based on protocol. Following script demonstrates the issue: ====================================================== from __future__ import print_function
import pickle, sys
class Foo:
__name__ = __qualname__ = "Foo.ref"
pass
Foo.ref = Foo
print(sys.version_info)
for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
print("{}:".format(proto), end=" ")
try:
pkl = pickle.dumps(Foo, proto)
print("Dump OK,", end=" ")
assert(pickle.loads(pkl) is Foo)
print("Load OK,")
except Exception as err:
print(repr(err)) ====================================================== Python3.7: This was introduced as a side effect of bpo-23611 (?). I can think of the following approaches to fix the issue and make the behavior consistent:
I had a stab at pickle.py and had a bit of success in doing point 3 above. Posting this issue for discussions. I would be happy to submit a PR for this issue. Thanks, |
I ran your script and didn't get RecursionError. The issue seems to be fixed. Python 3.8.2 (default, Apr 8 2020, 14:31:25)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import print_function
>>>
>>> import pickle, sys
>>>
>>> class Foo:
... __name__ = __qualname__ = "Foo.ref"
... pass
...
>>> Foo.ref = Foo
>>>
>>> print(sys.version_info)
sys.version_info(major=3, minor=8, micro=2, releaselevel='final', serial=0)
>>> for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
... print("{}:".format(proto), end=" ")
... try:
... pkl = pickle.dumps(Foo, proto)
... print("Dump OK,", end=" ")
... assert(pickle.loads(pkl) is Foo)
... print("Load OK,")
... except Exception as err:
... print(repr(err))
...
0: PicklingError("Can't pickle <class '__main__.Foo.ref'>: import of module '__main__' failed")
1: PicklingError("Can't pickle <class '__main__.Foo.ref'>: import of module '__main__' failed")
2: PicklingError("Can't pickle <class '__main__.Foo.ref'>: import of module '__main__' failed")
3: PicklingError("Can't pickle <class '__main__.Foo.ref'>: import of module '__main__' failed")
4: Dump OK, Load OK,
5: Dump OK, Load OK,
>>> |
Ahh. I misunderstood the problem. Pickle behaves differently when it is a circular reference. If you have a solution, I am waiting with curiosity. |
Serializing objects with complex __qualname__ (such as unbound methods and nested classes) by name no longer involves serializing parent objects by value in pickle protocols < 4.
Pickling unbound methods and nested classes is natively supported in protocol 4. In protocol 3 and lower, only top-level classes and functions (i.e. these that do not have a dot in This problem can be solved by forcing all parent objects to be serialized by name without using the normal dispatch mechanism: represent I consider this a bugfix because it matches the behavior in protocols < 4 with the behavior in protocols >= 4 which is used by default since 3.8 (see bpo-23403). I wish I did it from the beginning. |
Serializing objects with complex __qualname__ (such as unbound methods and nested classes) by name no longer involves serializing parent objects by value in pickle protocols < 4.
…onGH-122149) Serializing objects with complex __qualname__ (such as unbound methods and nested classes) by name no longer involves serializing parent objects by value in pickle protocols < 4. (cherry picked from commit dc07f65) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
…onGH-122149) Serializing objects with complex __qualname__ (such as unbound methods and nested classes) by name no longer involves serializing parent objects by value in pickle protocols < 4. (cherry picked from commit dc07f65) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
It was introduced in the previous commit.
Uh oh!
There was an error while loading. Please reload this page.
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:
bugs.python.org fields:
Linked PRs
The text was updated successfully, but these errors were encountered: