首页 > 解决方案 > 加载具有各种数据类型的字典列表时出现 EOFError

问题描述

我有字典列表,其中每个字典包含多个不同的项目。它在强化学习的训练过程中用作记忆回放,我需要创建一个备份文件以防万一该过程中断。每个 dict 代表一个环境步骤,因此结构相同,只有值不同。

每个 dict 包含的数据类型是:numpy.array、int、bool、string、 numpy 数组列表和float。Np 数组经过预处理,因此它确实包含实数浮点数 - 没有 NaN 或 Inf。

我的问题是,我尝试了多种方法,如何存储和加载文件,并且所有文件的行为都相似 - 备份创建没有问题,但有时(甚至根本没有 - 加载时根本没有发现其他地方错误的模式)它,它引发了EOFError。

列表中的最大数据量现在限制为 100k,创建的文件通常在 128MB 左右。

目前我正在通过pickle.dumps尝试它,但过去我尝试过简单的joblib转储/加载和copy.deepcopy来转储。

def _save_backup(self, path:str, name:str) -> dict:
    file_path = path+name+'_memory.joblib'
    with open(file_path, "wb") as f:
        serialized_mem = pickle.dumps(self._memory,protocol=pickle.HIGHEST_PROTOCOL)
        dump(serialized_mem,f)    
    return {'memory':file_path}


def _load_backup(self, data:dict):
    if os.path.exists(data['memory']):
        with open(data['memory'], "rb") as f:
            serialized_mem = load(f)
            self._memory = pickle.loads(serialized_mem)

编辑

回答tdelaney评论:

from joblib import dump, load import pickle

标签: pythonpicklejoblib

解决方案


几天没有错误,所以我猜它已修复。最后我使用了一些不同的东西,因为我MemoryError在保存过程中体验到在 32GB RAM 上运行 64 位 python 版本,其中一半以上可用。

这个实现似乎解决了加载MemoryErrorEOFError加载时

def save_backup(self, path:str, name:str) -> dict:
    # save memory
    file_path = path+name+'_memory.joblib'
    with open(file_path, "wb") as f:
        for data in list(self._memory):
            pickle.dump(data,f)  
    # save other files
    d = self._save_backup(path,name) # child class method
    # merge dicts
    d.update({'memory':file_path})
    return d


def load_backup(self, data:dict):
    # load memory
    if os.path.exists(data['memory']):
        with open(data['memory'], "rb") as f:
            self._memory.clear()
            while True:
                try:
                    self._memory.append(pickle.load(f))
                except EOFError:
                    break
    # load others
    self._load_backup(data) # child class method

推荐阅读