uqfoundation/dill

Class attributes changes at load if the object is in a list or tuple.

Closed this issue · 1 comments

I created a simple test code like the following. I expect the a in unpickled B objects (b1, b2, l1[0], l2[0]) should have the same value as the a in the original B object (b).

import dill

class A:
  pass

class B:
  a = A()
  def get_value(self):
    return self.a

b = B()
print(f'b: {b.get_value()}')

pickled_b = dill.dumps(b)

b1 = dill.loads(pickled_b)
print(f'b1: {b1.get_value()}')
b2 = dill.loads(pickled_b)
print(f'b2: {b2.get_value()}')


####

l = [B()]
print(f'l[0]: {l[0].get_value()}')

pickled_l = dill.dumps(l)

l1 = dill.loads(pickled_l)
print(f'l1[0]: {l1[0].get_value()}')
l2 = dill.loads(pickled_l)
print(f'l2[0]: {l2[0].get_value()}')

But, it worked as expected when dumping with the object directly, but not when dumping a list including the object. See below. Is this an intended behavior?

baeminbo$ python --version
Python 3.11.4
baeminbo$ pip list
Package    Version
---------- -------
dill       0.3.7
pip        23.1.2
setuptools 65.5.0

[notice] A new release of pip is available: 23.1.2 -> 23.3
[notice] To update, run: pip install --upgrade pip
baeminbo$ python dilltest.py 
b: <__main__.A object at 0x108d04d90>
b1: <__main__.A object at 0x108d04d90>
b2: <__main__.A object at 0x108d04d90>
l[0]: <__main__.A object at 0x108d04d90>
l1[0]: <__main__.A object at 0x1093e3150>
l2[0]: <__main__.A object at 0x1093e3950>

I close this ticket as I confirmed this is an intended behavior. The loads has ignore option that decides if using a reconstructed class or using the existing class in the __main__ module. The code is here.

In my sample, b=B() is a class in __main__, but l=[B()] is a type in builtins. For b1 and b2, newly reconstructed classes were discarded and replaced with the existing __main__.B. l1 and l2 didn't change the class for their elements, so the elements use the newly reconstructed classes which have different values for the class attribute a.