Pickle a frozen dataclass that has __slots__Usage of __slots__?GAE: ValueError: insecure string picklenamespace on python picklePickle errors with Python 3why Can't pickle a defauldict of objects in python?load pickle file for counvectorizerEOFError in pickle.load and file not found errorPickle: Storing the contents of variableHow can I save an Object like an Image Classifier prepared using Keras to my any file using Python?Problems in importing split in Python

If 1. e4 c6 is considered as a sound defense for black, why is 1. c3 so rare?

Feels like I am getting dragged into office politics

How long can a 35mm film be used/stored before it starts to lose its quality after expiry?

Floor tile layout process?

Why is Thanos so tough at the beginning of "Avengers: Endgame"?

Airbnb - host wants to reduce rooms, can we get refund?

Is this homebrew race based on Draco Volans balanced?

Who died in the Game of Thrones episode, "The Long Night"?

How to reply this mail from potential PhD professor?

Printing a string when grep does not get a match

What happened to Rhaegal?

Does it look bad as a candidate if I apply to two post-doctoral positions at the same national research laboratory?

Declining welcome lunch invitation at new job due to Ramadan

How do you center multiple equations that have multiple steps?

Unexpected email from Yorkshire Bank

Write to EXCEL from SQL DB using VBA script

When and why did journal article titles become descriptive, rather than creatively allusive?

Can commander tax be proliferated?

Password expiration with Password manager

How did Captain America use this power?

Copy line and insert it in a new position with sed or awk

Binary Numbers Magic Trick

How did Arya manage to disguise herself?

Can I use 1000v rectifier diodes instead of 600v rectifier diodes?



Pickle a frozen dataclass that has __slots__


Usage of __slots__?GAE: ValueError: insecure string picklenamespace on python picklePickle errors with Python 3why Can't pickle a defauldict of objects in python?load pickle file for counvectorizerEOFError in pickle.load and file not found errorPickle: Storing the contents of variableHow can I save an Object like an Image Classifier prepared using Keras to my any file using Python?Problems in importing split in Python






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








3















How do I pickle an instance of a frozen dataclass with __slots__? For example, the following code raises an exception in Python 3.7.0:



import pickle
from dataclasses import dataclass

@dataclass(frozen=True)
class A:
__slots__ = ('a',)
a: int

b = pickle.dumps(A(5))
pickle.loads(b)


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'a'


This works if I remove either the frozen or the __slots__. Is this just a bug?










share|improve this question




























    3















    How do I pickle an instance of a frozen dataclass with __slots__? For example, the following code raises an exception in Python 3.7.0:



    import pickle
    from dataclasses import dataclass

    @dataclass(frozen=True)
    class A:
    __slots__ = ('a',)
    a: int

    b = pickle.dumps(A(5))
    pickle.loads(b)


    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<string>", line 3, in __setattr__
    dataclasses.FrozenInstanceError: cannot assign to field 'a'


    This works if I remove either the frozen or the __slots__. Is this just a bug?










    share|improve this question
























      3












      3








      3


      0






      How do I pickle an instance of a frozen dataclass with __slots__? For example, the following code raises an exception in Python 3.7.0:



      import pickle
      from dataclasses import dataclass

      @dataclass(frozen=True)
      class A:
      __slots__ = ('a',)
      a: int

      b = pickle.dumps(A(5))
      pickle.loads(b)


      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<string>", line 3, in __setattr__
      dataclasses.FrozenInstanceError: cannot assign to field 'a'


      This works if I remove either the frozen or the __slots__. Is this just a bug?










      share|improve this question














      How do I pickle an instance of a frozen dataclass with __slots__? For example, the following code raises an exception in Python 3.7.0:



      import pickle
      from dataclasses import dataclass

      @dataclass(frozen=True)
      class A:
      __slots__ = ('a',)
      a: int

      b = pickle.dumps(A(5))
      pickle.loads(b)


      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<string>", line 3, in __setattr__
      dataclasses.FrozenInstanceError: cannot assign to field 'a'


      This works if I remove either the frozen or the __slots__. Is this just a bug?







      python pickle slots python-dataclasses






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Mar 22 at 19:59









      drhagendrhagen

      3,21942646




      3,21942646






















          1 Answer
          1






          active

          oldest

          votes


















          3














          The problem comes from pickle using the __setattr__ method of the instance when setting the state of the slots.



          The default __setsate__ is defined in load_build in _pickle.c line 6220.



          For the items in the state dict, the instance __dict__ is updated directly:



           if (PyObject_SetItem(dict, d_key, d_value) < 0)


          whereas for the items in the slotstate dict, the instance's __setattr__ is used:



          if (PyObject_SetAttr(inst, d_key, d_value) < 0)


          Now because the instance is frozen, __setattr__ raises FrozenInstanceError when loading.



          To circumvent this, you can define your own __setstate__ method which will use object.__setattr__, and not the instance's __setattr__.



          The docs give some sort of warning for this:




          There is a tiny performance penalty when using frozen=True: __init__() cannot use simple assignment to initialize fields, and must use object.__setattr__().




          It may also be good to define __getstate__ as the instance __dict__ is always None in your case. If you don't, the state argument of __setstate__ will be a tuple (None, 'a': 5), the first value being the value of the instance's __dict__ and the second the slotstate dict.



          import pickle
          from dataclasses import dataclass

          @dataclass(frozen=True)
          class A:
          __slots__ = ('a',)
          a: int

          def __getstate__(self):
          return dict(
          (slot, getattr(self, slot))
          for slot in self.__slots__
          if hasattr(self, slot)
          )

          def __setstate__(self, state):
          for slot, value in state.items():
          object.__setattr__(self, slot, value) # <- use object.__setattr__


          b = pickle.dumps(A(5))
          pickle.loads(b)


          I personally would not call it a bug as the pickling process is designed to be flexible, but there is room for a feature enhancement. A revision of the pickling protocol could fix this in future. Unless I am missing something and aside of the tiny performance penalty, using PyObject_GenericSetattr for all the slots might be a reasonable fix?






          share|improve this answer

























          • I updated the previously deleted answer. It all boils down to creating your own __setstate__ method to avoid a call to the instance's __setattr__.

            – Jacques Gaudin
            Mar 23 at 15:27






          • 1





            do you know why it works if the class doesn't have slots? does it not use setattr to initialize in that case?

            – Arne
            Mar 23 at 22:29











          • @Arne Good point, I just had a look in the source code of pickle and it seems that the other attributes are dealt with by modifying __dict__ directly whereas the slots use __setattr__. I'll take a deeper look and update.

            – Jacques Gaudin
            Mar 23 at 22:50






          • 2





            I have reported this issue and recommended your workaround to the Python bug tracker. Hopefully, it will make it into the standard library.

            – drhagen
            Mar 25 at 15:22











          • @drhagen Great, I'll try to compile with PyObject_GenericSetattr when I'll get a chance. Fingers crossed!

            – Jacques Gaudin
            Mar 25 at 16:40












          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55307017%2fpickle-a-frozen-dataclass-that-has-slots%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          3














          The problem comes from pickle using the __setattr__ method of the instance when setting the state of the slots.



          The default __setsate__ is defined in load_build in _pickle.c line 6220.



          For the items in the state dict, the instance __dict__ is updated directly:



           if (PyObject_SetItem(dict, d_key, d_value) < 0)


          whereas for the items in the slotstate dict, the instance's __setattr__ is used:



          if (PyObject_SetAttr(inst, d_key, d_value) < 0)


          Now because the instance is frozen, __setattr__ raises FrozenInstanceError when loading.



          To circumvent this, you can define your own __setstate__ method which will use object.__setattr__, and not the instance's __setattr__.



          The docs give some sort of warning for this:




          There is a tiny performance penalty when using frozen=True: __init__() cannot use simple assignment to initialize fields, and must use object.__setattr__().




          It may also be good to define __getstate__ as the instance __dict__ is always None in your case. If you don't, the state argument of __setstate__ will be a tuple (None, 'a': 5), the first value being the value of the instance's __dict__ and the second the slotstate dict.



          import pickle
          from dataclasses import dataclass

          @dataclass(frozen=True)
          class A:
          __slots__ = ('a',)
          a: int

          def __getstate__(self):
          return dict(
          (slot, getattr(self, slot))
          for slot in self.__slots__
          if hasattr(self, slot)
          )

          def __setstate__(self, state):
          for slot, value in state.items():
          object.__setattr__(self, slot, value) # <- use object.__setattr__


          b = pickle.dumps(A(5))
          pickle.loads(b)


          I personally would not call it a bug as the pickling process is designed to be flexible, but there is room for a feature enhancement. A revision of the pickling protocol could fix this in future. Unless I am missing something and aside of the tiny performance penalty, using PyObject_GenericSetattr for all the slots might be a reasonable fix?






          share|improve this answer

























          • I updated the previously deleted answer. It all boils down to creating your own __setstate__ method to avoid a call to the instance's __setattr__.

            – Jacques Gaudin
            Mar 23 at 15:27






          • 1





            do you know why it works if the class doesn't have slots? does it not use setattr to initialize in that case?

            – Arne
            Mar 23 at 22:29











          • @Arne Good point, I just had a look in the source code of pickle and it seems that the other attributes are dealt with by modifying __dict__ directly whereas the slots use __setattr__. I'll take a deeper look and update.

            – Jacques Gaudin
            Mar 23 at 22:50






          • 2





            I have reported this issue and recommended your workaround to the Python bug tracker. Hopefully, it will make it into the standard library.

            – drhagen
            Mar 25 at 15:22











          • @drhagen Great, I'll try to compile with PyObject_GenericSetattr when I'll get a chance. Fingers crossed!

            – Jacques Gaudin
            Mar 25 at 16:40
















          3














          The problem comes from pickle using the __setattr__ method of the instance when setting the state of the slots.



          The default __setsate__ is defined in load_build in _pickle.c line 6220.



          For the items in the state dict, the instance __dict__ is updated directly:



           if (PyObject_SetItem(dict, d_key, d_value) < 0)


          whereas for the items in the slotstate dict, the instance's __setattr__ is used:



          if (PyObject_SetAttr(inst, d_key, d_value) < 0)


          Now because the instance is frozen, __setattr__ raises FrozenInstanceError when loading.



          To circumvent this, you can define your own __setstate__ method which will use object.__setattr__, and not the instance's __setattr__.



          The docs give some sort of warning for this:




          There is a tiny performance penalty when using frozen=True: __init__() cannot use simple assignment to initialize fields, and must use object.__setattr__().




          It may also be good to define __getstate__ as the instance __dict__ is always None in your case. If you don't, the state argument of __setstate__ will be a tuple (None, 'a': 5), the first value being the value of the instance's __dict__ and the second the slotstate dict.



          import pickle
          from dataclasses import dataclass

          @dataclass(frozen=True)
          class A:
          __slots__ = ('a',)
          a: int

          def __getstate__(self):
          return dict(
          (slot, getattr(self, slot))
          for slot in self.__slots__
          if hasattr(self, slot)
          )

          def __setstate__(self, state):
          for slot, value in state.items():
          object.__setattr__(self, slot, value) # <- use object.__setattr__


          b = pickle.dumps(A(5))
          pickle.loads(b)


          I personally would not call it a bug as the pickling process is designed to be flexible, but there is room for a feature enhancement. A revision of the pickling protocol could fix this in future. Unless I am missing something and aside of the tiny performance penalty, using PyObject_GenericSetattr for all the slots might be a reasonable fix?






          share|improve this answer

























          • I updated the previously deleted answer. It all boils down to creating your own __setstate__ method to avoid a call to the instance's __setattr__.

            – Jacques Gaudin
            Mar 23 at 15:27






          • 1





            do you know why it works if the class doesn't have slots? does it not use setattr to initialize in that case?

            – Arne
            Mar 23 at 22:29











          • @Arne Good point, I just had a look in the source code of pickle and it seems that the other attributes are dealt with by modifying __dict__ directly whereas the slots use __setattr__. I'll take a deeper look and update.

            – Jacques Gaudin
            Mar 23 at 22:50






          • 2





            I have reported this issue and recommended your workaround to the Python bug tracker. Hopefully, it will make it into the standard library.

            – drhagen
            Mar 25 at 15:22











          • @drhagen Great, I'll try to compile with PyObject_GenericSetattr when I'll get a chance. Fingers crossed!

            – Jacques Gaudin
            Mar 25 at 16:40














          3












          3








          3







          The problem comes from pickle using the __setattr__ method of the instance when setting the state of the slots.



          The default __setsate__ is defined in load_build in _pickle.c line 6220.



          For the items in the state dict, the instance __dict__ is updated directly:



           if (PyObject_SetItem(dict, d_key, d_value) < 0)


          whereas for the items in the slotstate dict, the instance's __setattr__ is used:



          if (PyObject_SetAttr(inst, d_key, d_value) < 0)


          Now because the instance is frozen, __setattr__ raises FrozenInstanceError when loading.



          To circumvent this, you can define your own __setstate__ method which will use object.__setattr__, and not the instance's __setattr__.



          The docs give some sort of warning for this:




          There is a tiny performance penalty when using frozen=True: __init__() cannot use simple assignment to initialize fields, and must use object.__setattr__().




          It may also be good to define __getstate__ as the instance __dict__ is always None in your case. If you don't, the state argument of __setstate__ will be a tuple (None, 'a': 5), the first value being the value of the instance's __dict__ and the second the slotstate dict.



          import pickle
          from dataclasses import dataclass

          @dataclass(frozen=True)
          class A:
          __slots__ = ('a',)
          a: int

          def __getstate__(self):
          return dict(
          (slot, getattr(self, slot))
          for slot in self.__slots__
          if hasattr(self, slot)
          )

          def __setstate__(self, state):
          for slot, value in state.items():
          object.__setattr__(self, slot, value) # <- use object.__setattr__


          b = pickle.dumps(A(5))
          pickle.loads(b)


          I personally would not call it a bug as the pickling process is designed to be flexible, but there is room for a feature enhancement. A revision of the pickling protocol could fix this in future. Unless I am missing something and aside of the tiny performance penalty, using PyObject_GenericSetattr for all the slots might be a reasonable fix?






          share|improve this answer















          The problem comes from pickle using the __setattr__ method of the instance when setting the state of the slots.



          The default __setsate__ is defined in load_build in _pickle.c line 6220.



          For the items in the state dict, the instance __dict__ is updated directly:



           if (PyObject_SetItem(dict, d_key, d_value) < 0)


          whereas for the items in the slotstate dict, the instance's __setattr__ is used:



          if (PyObject_SetAttr(inst, d_key, d_value) < 0)


          Now because the instance is frozen, __setattr__ raises FrozenInstanceError when loading.



          To circumvent this, you can define your own __setstate__ method which will use object.__setattr__, and not the instance's __setattr__.



          The docs give some sort of warning for this:




          There is a tiny performance penalty when using frozen=True: __init__() cannot use simple assignment to initialize fields, and must use object.__setattr__().




          It may also be good to define __getstate__ as the instance __dict__ is always None in your case. If you don't, the state argument of __setstate__ will be a tuple (None, 'a': 5), the first value being the value of the instance's __dict__ and the second the slotstate dict.



          import pickle
          from dataclasses import dataclass

          @dataclass(frozen=True)
          class A:
          __slots__ = ('a',)
          a: int

          def __getstate__(self):
          return dict(
          (slot, getattr(self, slot))
          for slot in self.__slots__
          if hasattr(self, slot)
          )

          def __setstate__(self, state):
          for slot, value in state.items():
          object.__setattr__(self, slot, value) # <- use object.__setattr__


          b = pickle.dumps(A(5))
          pickle.loads(b)


          I personally would not call it a bug as the pickling process is designed to be flexible, but there is room for a feature enhancement. A revision of the pickling protocol could fix this in future. Unless I am missing something and aside of the tiny performance penalty, using PyObject_GenericSetattr for all the slots might be a reasonable fix?







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 26 at 7:34









          Arne

          3,01822444




          3,01822444










          answered Mar 22 at 20:09









          Jacques GaudinJacques Gaudin

          6,92232246




          6,92232246












          • I updated the previously deleted answer. It all boils down to creating your own __setstate__ method to avoid a call to the instance's __setattr__.

            – Jacques Gaudin
            Mar 23 at 15:27






          • 1





            do you know why it works if the class doesn't have slots? does it not use setattr to initialize in that case?

            – Arne
            Mar 23 at 22:29











          • @Arne Good point, I just had a look in the source code of pickle and it seems that the other attributes are dealt with by modifying __dict__ directly whereas the slots use __setattr__. I'll take a deeper look and update.

            – Jacques Gaudin
            Mar 23 at 22:50






          • 2





            I have reported this issue and recommended your workaround to the Python bug tracker. Hopefully, it will make it into the standard library.

            – drhagen
            Mar 25 at 15:22











          • @drhagen Great, I'll try to compile with PyObject_GenericSetattr when I'll get a chance. Fingers crossed!

            – Jacques Gaudin
            Mar 25 at 16:40


















          • I updated the previously deleted answer. It all boils down to creating your own __setstate__ method to avoid a call to the instance's __setattr__.

            – Jacques Gaudin
            Mar 23 at 15:27






          • 1





            do you know why it works if the class doesn't have slots? does it not use setattr to initialize in that case?

            – Arne
            Mar 23 at 22:29











          • @Arne Good point, I just had a look in the source code of pickle and it seems that the other attributes are dealt with by modifying __dict__ directly whereas the slots use __setattr__. I'll take a deeper look and update.

            – Jacques Gaudin
            Mar 23 at 22:50






          • 2





            I have reported this issue and recommended your workaround to the Python bug tracker. Hopefully, it will make it into the standard library.

            – drhagen
            Mar 25 at 15:22











          • @drhagen Great, I'll try to compile with PyObject_GenericSetattr when I'll get a chance. Fingers crossed!

            – Jacques Gaudin
            Mar 25 at 16:40

















          I updated the previously deleted answer. It all boils down to creating your own __setstate__ method to avoid a call to the instance's __setattr__.

          – Jacques Gaudin
          Mar 23 at 15:27





          I updated the previously deleted answer. It all boils down to creating your own __setstate__ method to avoid a call to the instance's __setattr__.

          – Jacques Gaudin
          Mar 23 at 15:27




          1




          1





          do you know why it works if the class doesn't have slots? does it not use setattr to initialize in that case?

          – Arne
          Mar 23 at 22:29





          do you know why it works if the class doesn't have slots? does it not use setattr to initialize in that case?

          – Arne
          Mar 23 at 22:29













          @Arne Good point, I just had a look in the source code of pickle and it seems that the other attributes are dealt with by modifying __dict__ directly whereas the slots use __setattr__. I'll take a deeper look and update.

          – Jacques Gaudin
          Mar 23 at 22:50





          @Arne Good point, I just had a look in the source code of pickle and it seems that the other attributes are dealt with by modifying __dict__ directly whereas the slots use __setattr__. I'll take a deeper look and update.

          – Jacques Gaudin
          Mar 23 at 22:50




          2




          2





          I have reported this issue and recommended your workaround to the Python bug tracker. Hopefully, it will make it into the standard library.

          – drhagen
          Mar 25 at 15:22





          I have reported this issue and recommended your workaround to the Python bug tracker. Hopefully, it will make it into the standard library.

          – drhagen
          Mar 25 at 15:22













          @drhagen Great, I'll try to compile with PyObject_GenericSetattr when I'll get a chance. Fingers crossed!

          – Jacques Gaudin
          Mar 25 at 16:40






          @drhagen Great, I'll try to compile with PyObject_GenericSetattr when I'll get a chance. Fingers crossed!

          – Jacques Gaudin
          Mar 25 at 16:40




















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55307017%2fpickle-a-frozen-dataclass-that-has-slots%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

          용인 삼성생명 블루밍스 목차 통계 역대 감독 선수단 응원단 경기장 같이 보기 외부 링크 둘러보기 메뉴samsungblueminx.comeh선수 명단용인 삼성생명 블루밍스용인 삼성생명 블루밍스ehsamsungblueminx.comeheheheh

          155 수학 과학 기타 둘러보기 메뉴eh추가해eh문서를 완성해