【问题标题】:os.read() gives OSError: [Errno 22] Invalid argument when reading large dataos.read() 给出 OSError: [Errno 22] Invalid argument when reading large data
【发布时间】:2018-12-02 10:11:06
【问题描述】:

我使用以下方法从二进制文件中的任何给定偏移量读取二进制数据。我拥有的二进制文件有 10GB 大,所以我通常会在需要时读取其中的一部分,方法是指定我应该从哪个偏移量start_read 以及要读取多少字节num_to_read。我使用Python 3.6.4 :: Anaconda, Inc.、平台Darwin-17.6.0-x86_64-i386-64bitos模块:

def read_from_disk(path, start_read, num_to_read, dim):
    fd = os.open(path, os.O_RDONLY)
    os.lseek(fd, start_read, 0)  # Where to (start_read) from the beginning 0
    raw_data = os.read(fd, num_to_read)  # How many bytes to read
    C = np.frombuffer(raw_data, dtype=np.int64).reshape(-1, dim).astype(np.int8)
    os.close(fd)
    return C

当要读取的数据块大约小于 2GB 时,此方法非常有效。当num_to_read > 2GG,我得到这个错误:

raw_data = os.read(fd, num_to_read)  # How many to read (num_to_read)
OSError: [Errno 22] Invalid argument

我不确定为什么会出现此问题以及如何解决它。非常感谢任何帮助。

【问题讨论】:

  • 你在什么平台上?
  • 你使用的是什么版本的 Python?
  • 听起来你用的是32位软件,需要64位才能访问超过2GB。
  • @abarnert Mac OSX。
  • @Barmar 不,他可能在 64 位平台上,但使用 32 位文件 API。

标签: python python-3.x operating-system


【解决方案1】:

os.read function 只是平台的read 函数的一个薄包装。

在某些平台上,这是一个无符号或有符号的 32 位 int,1 这意味着您在这些平台上一次可以read 的最大容量分别为 4GB 或 2GB。

因此,如果您想阅读更多内容,并且想要跨平台,则必须编写代码来处理此问题,并缓冲多个reads。

这可能有点麻烦,但您在这里有意使用最低级别的直接映射到操作系统 API 函数。如果你不喜欢这样:

  • 请改用从 open 返回的 io 模块对象 (Python 3.x) 或 file 对象 (2.7)。
  • 只需让 NumPy 读取文件 - 这将具有额外的优势,即 NumPy 足够聪明,不会一开始就尝试将整个内容读入内存。
  • 或者,对于这么大的文件,您可能希望降低级别并使用mmap(假设您使用的是 64 位平台)。

这里要做的正确的事情几乎可以肯定是前两者的结合。在 Python 3 中,它看起来像这样:

with open(path, 'rb', buffering=0) as f:
    f.seek(start_read)
    count = num_to_read // 8 # how many int64s to read
    return np.fromfile(f, dtype=np.int64, count=count).reshape(-1, dim).astype(np.int8)

1。对于 Windows,POSIX 仿真库的 _read 函数使用 int 作为 count 参数,它是 32 位有符号的。对于其他所有现代平台,请参阅 POSIX read,然后在您的平台上查找 size_tssize_toff_t 的定义。请注意,许多 POSIX 平台具有单独的 64 位类型和相应的功能,而不是将现有类型的含义更改为 64 位。 Python 将使用标准类型,而不是特殊的 64 位类型。

【讨论】:

  • 非常感谢。我很欣赏你的明确回答。如何在您的代码中指定num_to_read ?这对我来说非常重要,因为我不想阅读所有文件,只是其中的一部分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-07
  • 2021-08-26
  • 1970-01-01
  • 2020-07-29
  • 2019-06-29
  • 2018-06-15
  • 1970-01-01
相关资源
最近更新 更多