Message386090
Currently pickling functions and types stores modules by their name.
So I believe it is possible to support pickling module objects with the following code (based on the logic in PyPy, which supports pickling modules):
import copyreg
import types
import pickle
import sys
def picklemod(mod):
if mod.__name__ in sys.modules: # real modules
return (__import__, (mod.__name__, None, None, ('',)))
# module objects created manually:
return (types.ModuleType, (mod.__name__,), mod.__dict__)
copyreg.pickle(types.ModuleType, picklemod)
pickle.loads(pickle.dumps(sys)) # works
import http.server
pickle.loads(pickle.dumps(http.server)) # works for nested modules
fakemod = types.ModuleType('fakemod')
fakemod.field1 = 'whatever'
# This fake type is used instead of types.ModuleType in order to re-confuse pickle back on track.
# Should not have been necessary in the first place,
# but types.ModuleType has misconfigured fields according to pickle
# (and they are read-only).
class _types_ModuleType(types.ModuleType):
__module__ = 'types'
__name__ = __qualname__ = 'ModuleType'
_orig_types_ModuleType = types.ModuleType
# bad monkey-patching, but needed for the confusion to work
types.ModuleType = _types_ModuleType
dump = pickle.dumps(fakemod)
# not necessary, but to show unpickling is regardless correct
types.ModuleType = _orig_types_ModuleType
pickle.loads(dump).field1 # works
Disclaimer: I do not see any specific use for this, I was just surprised while trying to port snakeoil library to PyPy, which (snakeoil) uses sys module as an example of an unpicklable object (they should switch to a traceback for instance, but that is not the scope of this issue). |
|
Date |
User |
Action |
Args |
2021-02-01 19:17:44 | Arusekk | set | recipients:
+ Arusekk |
2021-02-01 19:17:44 | Arusekk | set | messageid: <1612207064.95.0.494686404563.issue43093@roundup.psfhosted.org> |
2021-02-01 19:17:44 | Arusekk | link | issue43093 messages |
2021-02-01 19:17:44 | Arusekk | create | |
|