如何在Python中使用持久方法来pickle类实例?

问题描述 投票:0回答:1

我想在 python 中序列化一个类实例并保持方法持久化。我尝试过 joblib 和 pickle,并且非常接近 dill,但不太明白。

问题就在这里。假设我想像这样腌制一个类实例:

import dill

class Test():
    def __init__(self, value=10):
        self.value = value
    def foo(self):
        print(f"Bar! Value is: {self.value}")

t = Test(value=20)
with open('Test.pkl', 'wb+') as fp:
    dill.dump(t, fp)

# Test it
print('Original: ')
t.foo()        # Prints "Bar! Value is: 20"

后来,

Test
的定义发生了变化,当我重新加载我的pickled对象时,方法是不同的:

class Test():
    def __init__(self, value=10):
        self.value = value
    def foo(self):
        print("...not bar?")

with open('Test.pkl', 'rb') as fp:
    t2 = dill.load(fp)

# Test it
print('Reloaded: ')
t2.foo()        # Prints "...not bar?"

现在在重新加载的情况下,属性值被保留(

t2.value
为20)。通过使用 dill 序列化类而不是实例,我可以非常接近我想要的,如下所示:

class Test():
    def __init__(self, value=10):
        self.value = value
    def foo(self):
        print(f"Bar! Value is: {self.value}")

t = Test(value=20)
with open('Test.pkl', 'wb+') as fp:
    dill.dump(Test, fp)

# Test it
print('Original: ')
t.foo()        # Prints "Bar! Value is: 20"

但是当我重建它时,我得到了旧方法(我想要的),但我丢失了实例的属性

t
(在这种情况下,我得到默认值10而不是实例值20):

class Test():
    def __init__(self, value=10):
        self.value = value
    def foo(self):
        print("...not bar?")

with open('Test.pkl', 'rb') as fp:
    test_class = dill.load(fp)
    t2 = test_class()

# Test it
print('Reloaded: ')
t2.foo()        # Prints "Bar! Value is: 10"

在我的实际用例中,类实例中有很多属性。我希望能够腌制属性和方法,以便以后的源代码更改不会使该特定对象不可恢复。

目前,为了恢复这些对象,我正在复制源代码文件,但导入变得非常混乱——很多

sys.path
操作变得令人困惑,以确保我加载正确的旧源代码。我还可以做一些事情,我用 dill 腌制类定义,然后将所有属性保存到 json 或其他东西并以这种方式重建,但我想知道是否有一种简单的方法可以用 dill 或我的其他一些包来做到这一点还没有发现。对我来说这似乎是一个简单的用例。

python python-3.x pickle dill
1个回答
0
投票
  • 您可以尝试使用 cloudpickle 来实现这一点,下面的示例实现了我相信您所要求的目标。
  • 我强烈建议在使用它之前编写一些测试来检查您想要实现的确切功能。
  • 他们在 github 上提到,这只能用于在 完全相同版本的 Python 之间发送对象。
import cloudpickle

# Initial class
class Test:
    def __init__(self, value=10):
        self.value = value
    def foo(self):
        print(f"Bar! Value is: {self.value}")

t = Test(value=20)
with open('test.pkl', 'wb') as f:
    cloudpickle.dump(t, f)

# Re-definition of class
class Test:
    def __init__(self, value=10):
        self.value = value
    def foo(self):
        print("...not bar?")

# Load original instance
with open('test.pkl', 'rb') as f:
    t2 = cloudpickle.load(f)

t2.foo()
# Bar! Value is: 20
© www.soinside.com 2019 - 2024. All rights reserved.