【问题标题】:Is there a way around "OSError: [Errno 22] Invalid argument"?有没有办法解决“OSError:[Errno 22] Invalid argument”?
【发布时间】:2020-10-13 18:56:39
【问题描述】:

我正在尝试将变量保存到要调用的文件中。这通常是用泡菜完成的,所以这就是我开始的。我从我的数据中抽取了一小部分样本,看看它是否会保存。该样本为 20 mb。我的总数据大约是 205 倍(4001 mb)。此示例已保存,但当我尝试保存完整数据时,我遇到了OSError: [Errno 22] Invalid argument

经过进一步探索,我发现pickle有一个bug,不允许你生成更大的4gb文件。这比我的数据占用的存储量要少一些。

在此声明:Any idea with "OSError: [Errno 22] Invalid argument" in pickle.dump?

这里说这是我使用的 OS X 上的问题https://bugs.python.org/issue24658

我找到了这段代码但看不懂

import pickle
 
class MacOSFile(object):
 
    def __init__(self, f):
        self.f = f
 
    def __getattr__(self, item):
        return getattr(self.f, item)
 
    def read(self, n):
        # print("reading total_bytes=%s" % n, flush=True)
        if n >= (1 << 31):
            buffer = bytearray(n)
            idx = 0
            while idx < n:
                batch_size = min(n - idx, 1 << 31 - 1)
                # print("reading bytes [%s,%s)..." % (idx, idx + batch_size), end="", flush=True)
                buffer[idx:idx + batch_size] = self.f.read(batch_size)
                # print("done.", flush=True)
                idx += batch_size
            return buffer
        return self.f.read(n)
 
    def write(self, buffer):
        n = len(buffer)
        print("writing total_bytes=%s..." % n, flush=True)
        idx = 0
        while idx < n:
            batch_size = min(n - idx, 1 << 31 - 1)
            print("writing bytes [%s, %s)... " % (idx, idx + batch_size), end="", flush=True)
            self.f.write(buffer[idx:idx + batch_size])
            print("done.", flush=True)
            idx += batch_size

def pickle_dump(obj, file_path):
    with open(file_path, "wb") as f:
        return pickle.dump(obj, MacOSFile(f), protocol=pickle.HIGHEST_PROTOCOL)
 
 
def pickle_load(file_path):
    with open(file_path, "rb") as f:

        return pickle.load(MacOSFile(f))

在我的代码中

with open("file.pickle", "wb") as f: 
    pickle.dump((boards, value), f)

我使用了一个简单的转储

我想知道是否有人能够解释上面提供的代码的作用以及它是如何工作的,如果可以的话?来源(https://www.programmersought.com/article/3832726678/)

重新创建它的一种简单方法是创建一个庞大的列表并保存它。

【问题讨论】:

  • 声称当limits.h 中的INT_MAX 写入结束时,OSX 上的底层write 会失败。此代码以较小的块写入以避免该错误。它似乎有问题,因为它没有根据请求检查实际的写入/读取计数。但是修复这些错误,它可能会起作用。
  • @tdelaney 非常感谢你,它工作得很好。

标签: python python-3.x pickle


【解决方案1】:

此代码需要一分钟,但会在您想要读取或写入时保存数据,您需要使用提供的读取和写入功能:

import pickle
 
class MacOSFile(object):
 
    def __init__(self, f):
        self.f = f
 
    def __getattr__(self, item):
        return getattr(self.f, item)
 
    def read(self, n):
        # print("reading total_bytes=%s" % n, flush=True)
        if n >= (1 << 31):
            buffer = bytearray(n)
            idx = 0
            while idx < n:
                batch_size = min(n - idx, 1 << 31 - 1)
                # print("reading bytes [%s,%s)..." % (idx, idx + batch_size), end="", flush=True)
                buffer[idx:idx + batch_size] = self.f.read(batch_size)
                # print("done.", flush=True)
                idx += batch_size
            return buffer
        return self.f.read(n)
 
    def write(self, buffer):
        n = len(buffer)
        print("writing total_bytes=%s..." % n, flush=True)
        idx = 0
        while idx < n:
            batch_size = min(n - idx, 1 << 31 - 1)
            print("writing bytes [%s, %s)... " % (idx, idx + batch_size), end="", flush=True)
            self.f.write(buffer[idx:idx + batch_size])
            print("done.", flush=True)
            idx += batch_size

def pickle_dump(obj, file_path):
    with open(file_path, "wb") as f:
        return pickle.dump(obj, MacOSFile(f), protocol=pickle.HIGHEST_PROTOCOL)
 
 
def pickle_load(file_path):
    with open(file_path, "rb") as f:

        return pickle.load(MacOSFile(f))

【讨论】:

    猜你喜欢
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 2020-07-29
    • 2019-06-29
    • 2018-06-15
    • 1970-01-01
    • 2021-08-26
    相关资源
    最近更新 更多