python - pickle 是否在大文件上随机失败并出现 OSError?

标签 python python-3.x pickle

问题陈述

我正在使用 python3 并尝试 pickle 一个 IntervalTrees 字典,它的重量大约为 2 到 3 GB。这是我的控制台输出:

10:39:25 - project: INFO - Checking if motifs file was generated by pickle...
10:39:25 - project: INFO -   - Motifs file does not seem to have been generated by pickle, proceeding to parse...
10:39:38 - project: INFO -   - Parse complete, constructing IntervalTrees...
11:04:05 - project: INFO -   - IntervalTree construction complete, saving pickle file for next time.
Traceback (most recent call last):
  File "/Users/alex/Documents/project/src/project.py", line 522, in dict_of_IntervalTree_from_motifs_file
    save_as_pickled_object(motifs, output_dir + 'motifs_IntervalTree_dictionary.pickle')
  File "/Users/alex/Documents/project/src/project.py", line 269, in save_as_pickled_object
    def save_as_pickled_object(object, filepath): return pickle.dump(object, open(filepath, "wb"))
OSError: [Errno 22] Invalid argument

我尝试保存的行是

def save_as_pickled_object(object, filepath): return pickle.dump(object, open(filepath, "wb"))

错误可能在 save_as_pickled_object 被调用 15 分钟后出现(11:20)。

我用图案文件的一小部分尝试了这个,它工作正常,所有代码完全相同,所以它一定是规模问题。 python 3.6 中的 pickle 是否存在与您尝试 pickle 的规模有关的已知错误?一般来说, pickle 大文件是否存在已知错误?是否有解决此问题的已知方法?

谢谢!

更新:这个问题可能与 Python 3 - Can pickle handle byte objects larger than 4GB? 重复

解决方案

这是我改用的代码。

def save_as_pickled_object(obj, filepath):
    """
    This is a defensive way to write pickle.write, allowing for very large files on all platforms
    """
    max_bytes = 2**31 - 1
    bytes_out = pickle.dumps(obj)
    n_bytes = sys.getsizeof(bytes_out)
    with open(filepath, 'wb') as f_out:
        for idx in range(0, n_bytes, max_bytes):
            f_out.write(bytes_out[idx:idx+max_bytes])


def try_to_load_as_pickled_object_or_None(filepath):
    """
    This is a defensive way to write pickle.load, allowing for very large files on all platforms
    """
    max_bytes = 2**31 - 1
    try:
        input_size = os.path.getsize(filepath)
        bytes_in = bytearray(0)
        with open(filepath, 'rb') as f_in:
            for _ in range(0, input_size, max_bytes):
                bytes_in += f_in.read(max_bytes)
        obj = pickle.loads(bytes_in)
    except:
        return None
    return obj

最佳答案

Alex,如果我没记错的话,这份错误报告完美地描述了你的问题。

http://bugs.python.org/issue24658

作为解决方法,我认为您可以使用 pickle.dumps 而不是 pickle.dump,然后以小于 2**31 的 block 的形式写入您的文件。

关于python - pickle 是否在大文件上随机失败并出现 OSError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42653386/

相关文章:

python - Pandas 多索引切片下属级别范围的最佳方法

python - 使用文本文档更改列表中的项目

python - 从元组列表创建嵌套字典的快速方法,无需 for 循环

python-2.7 - pickle 中 io 与字符串内容的不同行为

javascript - Django Python 中未加载静态文件

python - 迭代 for 循环并应用 np.union1d

python - 将鼠标悬停在 pandas 数据框上时如何注释标签

python - 将 python 对象写入磁盘而不加载到内存中?

python - 如何动态创建 Luigi 任务

python - 使用 web.py 从表单提交启动的进程动态输出值