
This issue trackerhas been migrated toGitHub, and is currentlyread-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.
Created on2018-02-19 10:46 byserhiy.storchaka, last changed2022-04-11 14:58 byadmin. This issue is nowclosed.
| Pull Requests | |||
|---|---|---|---|
| URL | Status | Linked | Edit |
| PR 6216 | merged | levkivskyi,2018-03-24 20:02 | |
| PR 6264 | merged | miss-islington,2018-03-26 22:02 | |
| PR 6376 | merged | levkivskyi,2018-04-04 22:30 | |
| PR 6378 | merged | miss-islington,2018-04-05 00:25 | |
| Messages (15) | |||
|---|---|---|---|
| msg312346 -(view) | Author: Serhiy Storchaka (serhiy.storchaka)*![]() | Date: 2018-02-19 10:46 | |
In 3.6 typing types are pickled by names:>>> import pickle, pickletools, typing>>> pickletools.optimize(pickle.dumps(typing.List))b'\x80\x03ctyping\nList\n.'>>> pickletools.dis(pickletools.optimize(pickle.dumps(typing.List))) 0: \x80 PROTO 3 2: c GLOBAL 'typing List' 15: . STOPhighest protocol among opcodes = 2The side effect of this is that they are considered atomic by the copy module.In 3.7 the pickle data contains all private attributes.>>> pickletools.optimize(pickle.dumps(typing.List))b'\x80\x03ctyping\n_GenericAlias\n)\x81}(X\x05\x00\x00\x00_inst\x89X\x08\x00\x00\x00_special\x88X\x05\x00\x00\x00_nameX\x04\x00\x00\x00ListX\n\x00\x00\x00__origin__cbuiltins\nlist\nX\x08\x00\x00\x00__args__ctyping\nTypeVar\n)\x81q\x00}(X\x04\x00\x00\x00nameX\x01\x00\x00\x00TX\x05\x00\x00\x00boundNX\x0b\x00\x00\x00constraints)X\x02\x00\x00\x00co\x89X\x06\x00\x00\x00contra\x89ub\x85X\x0e\x00\x00\x00__parameters__h\x00\x85X\t\x00\x00\x00__slots__Nub.'>>> pickletools.dis(pickletools.optimize(pickle.dumps(typing.List))) 0: \x80 PROTO 3 2: c GLOBAL 'typing _GenericAlias' 24: ) EMPTY_TUPLE 25: \x81 NEWOBJ 26: } EMPTY_DICT 27: ( MARK 28: X BINUNICODE '_inst' 38: \x89 NEWFALSE 39: X BINUNICODE '_special' 52: \x88 NEWTRUE 53: X BINUNICODE '_name' 63: X BINUNICODE 'List' 72: X BINUNICODE '__origin__' 87: c GLOBAL 'builtins list' 102: X BINUNICODE '__args__' 115: c GLOBAL 'typing TypeVar' 131: ) EMPTY_TUPLE 132: \x81 NEWOBJ 133: q BINPUT 0 135: } EMPTY_DICT 136: ( MARK 137: X BINUNICODE 'name' 146: X BINUNICODE 'T' 152: X BINUNICODE 'bound' 162: N NONE 163: X BINUNICODE 'constraints' 179: ) EMPTY_TUPLE 180: X BINUNICODE 'co' 187: \x89 NEWFALSE 188: X BINUNICODE 'contra' 199: \x89 NEWFALSE 200: u SETITEMS (MARK at 136) 201: b BUILD 202: \x85 TUPLE1 203: X BINUNICODE '__parameters__' 222: h BINGET 0 224: \x85 TUPLE1 225: X BINUNICODE '__slots__' 239: N NONE 240: u SETITEMS (MARK at 27) 241: b BUILD 242: . STOPhighest protocol among opcodes = 2Unpickling it creates a new object. And I'm not sure all invariants are satisfied.In additional to lesses efficiency and lost of preserving identity, such pickle can be incompatible with old Python versions and future Python versions if the internal representation of typing types will be changed. | |||
| msg312354 -(view) | Author: Guido van Rossum (gvanrossum)*![]() | Date: 2018-02-19 16:21 | |
I think it would be nice it would be pickled by name so the pickles arecompatible between Python versions.What would we do for List[int]?How are regular ABCs pickled? | |||
| msg312355 -(view) | Author: Ivan Levkivskyi (levkivskyi)*![]() | Date: 2018-02-19 16:43 | |
Here is the situation for 3.6 and before:Generic classes are all actual class objects, so they are pickled as immutable. However this creates a problem, parameterized generics, such as `List[int]` _cannot_ be pickled in 3.6 and before, seehttps://github.com/python/typing/issues/511 (and this is something very hard to fix).Here is the situation for 3.7:Almost no generics are actual class objects, so they are pickled as usual. This also fixes the pickling problems in 3.6. However, there is one problematic thing, type variables, they should be pickled as immutable (i.e. by name reference), but I didn't have time to fix this, this is tracked inhttps://github.com/python/typing/issues/512What is interesting this issue adds here is an idea that we can treat special typing aliases that are conceptually "unique" also as immutable. For example, `typing.List` will be pickled as "typing.List", while `typing.List[int]` will be pickled as _GenericAlias(<builtins.list>, args=(<builtins.int>,), ...)Conveniently, all the special typing aliases are already marked with `_special=True`, so the potential solution would be like this:class _GenericAlias: ... def __reduce__(self): if self._special: return 'typing.' + self._name return super().__reduce__() | |||
| msg312357 -(view) | Author: Serhiy Storchaka (serhiy.storchaka)*![]() | Date: 2018-02-19 16:58 | |
I think it would be better to pickle `typing.List[int]` as `operator.getitem(typing.List, int)`. def __reduce__(self): if self._special: return self._name # __module__ = 'typing' index = self._args if len(index) == 1: index, = index return operator.getitem, (self._unparametrized, index)And there may be a special case for Union. I tried to implement this, but it seems to me that parametrized type doesn't have a reference to unparametrized type, and I don't know this code enough for writing idiomatic code. | |||
| msg312377 -(view) | Author: Guido van Rossum (gvanrossum)*![]() | Date: 2018-02-19 22:39 | |
I'm honestly not too concerned about what happens with List[int] (thoughdoing a sensible thing here is not wrong :-), but I feel strongly that apickle containing a reference to typing.List should be compatible betweenPython 3.6 and 3.7. | |||
| msg312952 -(view) | Author: Ned Deily (ned.deily)*![]() | Date: 2018-02-26 20:47 | |
So we need a decision on this about what, if anything, to do for 3.7. The 3.7.0 ABI freeze is in 3.7.0b3; it would be better to get it resolved for 3.7.0b2. | |||
| msg312953 -(view) | Author: Ivan Levkivskyi (levkivskyi)*![]() | Date: 2018-02-26 20:49 | |
I am sick now, so can't work on this. There is a small chance I will be able to work on this issue this week. Is it possible to fix this in 3.7b3? | |||
| msg312954 -(view) | Author: Ned Deily (ned.deily)*![]() | Date: 2018-02-26 20:52 | |
> Is it possible to fix this in 3.7b3?Yes. Get well first! | |||
| msg312955 -(view) | Author: Ivan Levkivskyi (levkivskyi)*![]() | Date: 2018-02-26 20:52 | |
Thank you, Ned! | |||
| msg314482 -(view) | Author: Ivan Levkivskyi (levkivskyi)*![]() | Date: 2018-03-26 22:01 | |
New changeset834940375ae88bc95794226dd8eff1f25fba1cf9 by Ivan Levkivskyi in branch 'master':bpo-32873: Treat type variables and special typing forms as immutable by copy and pickle (GH-6216)https://github.com/python/cpython/commit/834940375ae88bc95794226dd8eff1f25fba1cf9 | |||
| msg314483 -(view) | Author: miss-islington (miss-islington) | Date: 2018-03-26 22:29 | |
New changesetd0e04c82448c750d4dc27f2bddeddea74bd353ff by Miss Islington (bot) in branch '3.7':bpo-32873: Treat type variables and special typing forms as immutable by copy and pickle (GH-6216)https://github.com/python/cpython/commit/d0e04c82448c750d4dc27f2bddeddea74bd353ff | |||
| msg314952 -(view) | Author: Will T (wrmsr) | Date: 2018-04-04 21:47 | |
I believe I hit a bug with this fix (just pulled the code a few min ago): In [10]: pickle.loads(pickle.dumps(typing.List)) Out[10]: typing.List In [11]: pickle.loads(pickle.dumps(typing.FrozenSet)) --------------------------------------------------------------------------- PicklingError Traceback (most recent call last) <ipython-input-11-be060c6090e3> in <module>() ----> 1 pickle.loads(pickle.dumps(typing.FrozenSet)) PicklingError: Can't pickle typing.Frozenset: attribute lookup Frozenset on typing failedThe cause is in _GenericAlias.__init__ name = orig_name[0].title() + orig_name[1:]Maybe just pass the name explicitly?For context I originally hit this trying to explicitly getattr(typing, alias_name) not by pickling but I'm pleased to see that's at least apparently intended to be valid use (I need to get the underlying special's parameter variance which is lost when you give it args). | |||
| msg314955 -(view) | Author: Ivan Levkivskyi (levkivskyi)*![]() | Date: 2018-04-04 22:06 | |
Apparently there is another type with a similar problem -- DefaultDict.Will fix this now. | |||
| msg314963 -(view) | Author: Ivan Levkivskyi (levkivskyi)*![]() | Date: 2018-04-05 00:25 | |
New changeset2a363d2930e29ec6d8a774973ed5a4965f881f5f by Ivan Levkivskyi in branch 'master':bpo-32873: Remove a name hack for generic aliases in typing module (GH-6376)https://github.com/python/cpython/commit/2a363d2930e29ec6d8a774973ed5a4965f881f5f | |||
| msg314964 -(view) | Author: miss-islington (miss-islington) | Date: 2018-04-05 00:46 | |
New changeset04eac02088f60192c7e54c7364bcaa892d7c05cf by Miss Islington (bot) in branch '3.7':bpo-32873: Remove a name hack for generic aliases in typing module (GH-6376)https://github.com/python/cpython/commit/04eac02088f60192c7e54c7364bcaa892d7c05cf | |||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022-04-11 14:58:57 | admin | set | github: 77054 |
| 2018-04-05 00:46:42 | miss-islington | set | messages: +msg314964 |
| 2018-04-05 00:25:39 | miss-islington | set | pull_requests: +pull_request6090 |
| 2018-04-05 00:25:17 | levkivskyi | set | messages: +msg314963 |
| 2018-04-04 22:30:49 | levkivskyi | set | pull_requests: +pull_request6088 |
| 2018-04-04 22:06:30 | levkivskyi | set | messages: +msg314955 |
| 2018-04-04 21:47:35 | wrmsr | set | nosy: +wrmsr messages: +msg314952 |
| 2018-03-26 22:37:30 | levkivskyi | set | status: open -> closed resolution: fixed stage: patch review -> resolved |
| 2018-03-26 22:29:14 | miss-islington | set | nosy: +miss-islington messages: +msg314483 |
| 2018-03-26 22:02:33 | miss-islington | set | pull_requests: +pull_request5990 |
| 2018-03-26 22:01:20 | levkivskyi | set | messages: +msg314482 |
| 2018-03-24 20:02:38 | levkivskyi | set | keywords: +patch stage: patch review pull_requests: +pull_request5961 |
| 2018-02-26 20:52:47 | levkivskyi | set | messages: +msg312955 |
| 2018-02-26 20:52:04 | ned.deily | set | messages: +msg312954 |
| 2018-02-26 20:49:50 | levkivskyi | set | messages: +msg312953 |
| 2018-02-26 20:47:14 | ned.deily | set | priority: normal -> deferred blocker nosy: +ned.deily messages: +msg312952 |
| 2018-02-19 22:39:51 | gvanrossum | set | messages: +msg312377 |
| 2018-02-19 16:58:48 | serhiy.storchaka | set | messages: +msg312357 |
| 2018-02-19 16:43:36 | levkivskyi | set | messages: +msg312355 |
| 2018-02-19 16:21:21 | gvanrossum | set | messages: +msg312354 |
| 2018-02-19 10:46:45 | serhiy.storchaka | create | |