为什么我的 Pickled 类给我 AttributeError: Can't get attribute 'MyClass'?

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

我尝试在两台不同的计算机上运行它,但每当我尝试加载pickle文件时,我都会得到:

AttributeError: Can't get attribute 'MyClass'

我试图了解我做错了什么,或者我对泡菜的作用是否有错误的理解?我该如何解决它?

我想知道为什么当我只调用 xyz.fit(data) 时 SKLearn 就可以工作,并且在加载 pickle 后它就可以工作,同时我调用 xyz.add_one(5) 的代码给了我一个错误?

我自己的班级: 制作泡菜:

import base64
import pickle

class MyClass:
    def add_one(self, x):
        return x + 1

obj = MyClass()

add_one = obj

pickled_data = pickle.dumps(add_one)

encoded_data = base64.b64encode(pickled_data)

with open("some_location.txt", "wb") as f:
    f.write(encoded_data)

在另一台计算机上加载 Pickle:

import base64
import pickle

# Read the encoded data from the file
with open("some_location.txt", "rb") as f:
    encoded_data = f.read()

pickled_data = base64.b64decode(encoded_data)

loaded = pickle.loads(pickled_data)

result = loaded.add_one(5)  
print(result)  # Output: 6
# Errored out: AttributeError: Can't get attribute 'MyClass'

同时,当我尝试使用 SKlearn 执行此操作时,我能够毫无问题地调用类中保存的方法。 示例:

from sklearn import svm
from sklearn import datasets
import pickle

iris = datasets.load_iris()
X, y = iris.data, iris.target

clf = svm.SVC()
clf.fit(X, y)  

with open("/dbfs/FileStore/tables/tmp/test.txt",'wb') as f:
    pickle.dump(clf,f)

在单独的计算机中:

import pickle

X = [[5.1, 3.5, 1.4, 0.2],
 [4.9, 3,  1.4, 0.2],
 [4.7, 3.2, 1.3, 0.2],
 [4.6, 3.1, 1.5, 0.2],
 [5,  3.6, 1.4, 0.2]]

with open('/dbfs/FileStore/tables/tmp/test.txt', 'rb') as f:
    clf2 = pickle.load(f)


print(clf2.predict(X[0:5]))
python class scikit-learn pickle
1个回答
0
投票

完整的错误输出在这里很有帮助。如果我们将第一个脚本放入

t.py
中,将第二个脚本放入
y.py
中,然后依次运行一个脚本,我们会得到:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/private/tmp/tmpvenv-ec8f9/y.py", line 10, in <module>
    loaded = pickle.loads(pickled_data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: Can't get attribute 'MyClass' on <module 'y' from '/private/tmp/tmpvenv-ec8f9/y.py'>

最后一行向我们表明,Python 正在尝试重新水合对象,并正在寻找

MyClass
类型来重新创建
obj
。所以它在我们正在运行的文件中寻找该类(
on <module 'y' from '/private/tmp/tmpvenv-ec8f9/y.py'>
)。但是,当然,
MyClass
不存在。

这里的问题是,当我们尝试再次加载正在腌制的对象时,无法找到该对象的类型。当您 pickle

sklearn.SVC
实例时,该代码可能适合您,因为您在两个环境中都安装了该库,因此当您加载 pickle 对象时它始终可用。 (可以确认一下吗?)


我们可以通过在

MyClass
中添加
y.py
来完成这项工作(尽管可能会产生令人惊讶的结果)。如果我们添加:

  import base64
  import pickle

+ class MyClass:
+     def add_one(self, x):
+         return x + 10


  # Read the encoded data from the file
  with open("some_location.txt", "rb") as f:
      encoded_data = f.read()

  pickled_data = base64.b64decode(encoded_data)

  loaded = pickle.loads(pickled_data)

  result = loaded.add_one(5)
  print(result)

然后当我们运行它时我们得到:

$ python -m y
15

加载腌制对象已恢复,但使用

MyClass
中定义的
y.py
类型,这与原来的有所不同!

© www.soinside.com 2019 - 2024. All rights reserved.