You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pickle功能正常但pytest测试失败,报AttributeError错误

问题原因

你遇到的报错核心是pickle无法序列化局部类的实例。在test_object fixture里,TestObject是定义在函数内部的局部类——pickle序列化对象时,需要能在全局命名空间中找到类的定义,但局部类的作用域仅限于函数内部,序列化时无法被准确定位,因此触发AttributeError。

解决方案

方案1:把测试类移到模块级(最推荐)

将TestObject从fixture函数中移到测试模块的顶层作用域,让pickle能找到类的全局引用:

# tests.test_persist.py
from pathlib import Path
import pytest
from lib.persist import obj_pickle

TEST_DIR = Path("test_dir")

# 把TestObject移到模块顶层
class TestObject():
    def __init__(self, instance_file_name):
        self.instance_file_name = instance_file_name
        self.data = "This is a test object."

@pytest.fixture
def test_object():
    test_object = TestObject("test_object_file")
    return test_object

def test_obj_pickle(test_object):
    obj_pickle(test_object, Path(TEST_DIR))
    path = Path(TEST_DIR, "test_object_file" + ".pkl")
    assert path.exists()

方案2:自定义类的__reduce__方法

如果必须在fixture内部定义类,可以给类实现__reduce__方法,手动告诉pickle如何序列化/反序列化实例:

@pytest.fixture
def test_object():
    class TestObject():
        def __init__(self, instance_file_name):
            self.instance_file_name = instance_file_name
            self.data = "This is a test object."
        
        def __reduce__(self):
            # 返回元组:(重建类的函数, 重建参数, 对象的状态字典)
            return (self.__class__, (self.instance_file_name,), self.__dict__)

    test_object = TestObject("test_object_file")
    return test_object

方案3:用cloudpickle替代标准pickle

cloudpickle是第三方库,支持序列化局部类、lambda等标准pickle不兼容的对象。先安装:

pip install cloudpickle

然后修改lib.persist.py的导入:

# lib.persist.py
from pathlib import Path
import cloudpickle as pickle  # 替换成cloudpickle

def obj_pickle(obj: object, dir:Path, protocol: int = None) -> None:
    """
    Pickle an object to a byte file.
    """
    if not dir.exists():
        dir.mkdir(parents=True, exist_ok=True)
    path = Path(dir, obj.instance_file_name + '.pkl')
    with open(path, "wb") as file_handle:
        pickle.dump(obj, file_handle, protocol=protocol if protocol else pickle.HIGHEST_PROTOCOL)
    print(f"{obj.__class__.__name__} object {obj.instance_file_name} saved to {path}")
验证

修改完成后重新运行pytest,报错会消失,测试可正常通过。

内容的提问来源于stack exchange,提问作者Paul C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 10:37:43