Python 无法在 r+ 模式下打开 11gb csv 但在 r 模式下打开

标签 python windows file-io

我在处理一些循环遍历一堆 .csvs 的代码时遇到问题,如果其中没有任何内容(即以 \n 换行符结尾的文件),则删除最后一行

p>

我的代码在所有文件上都能成功运行,除了一个文件,它是目录中最大的文件,大小为 11gb。第二大文件是 4.5gb。

它失败的行很简单:

with open(path_str,"r+") as my_file:

我收到以下消息:

IOError: [Errno 22] invalid mode ('r+') or filename: 'F:\\Shapefiles\\ab_premium\\processed_csvs\\a.csv'

我使用 os.file.join 创建的 path_str 以避免错误,我尝试将文件重命名为 a.csv 只是为了确保文件名没有任何异常。这没有区别。

更奇怪的是,该文件很高兴以 r 模式打开。 IE。以下代码工作正常:

with open(path_str,"r") as my_file:

我尝试在读取模式下浏览文件,很高兴读取文件开头、结尾和中间的字符。

有谁知道 Python 可以处理的文件大小有任何限制,或者为什么我可能会收到此错误?我使用的是 Windows 7 64 位系统并且有 16GB 的内存。

最佳答案

Python 2 中的默认 I/O 堆栈位于 CRT FILE 流之上。在 Windows 上,它们构建在使用文件描述符的 POSIX 仿真 API 之上(它依次位于用户模式 ​​Windows API 之上,而后者又位于内核模式 I/O 系统之上,而内核模式 I/O 系统本身就是一个深层系统基于 I/O 请求数据包;硬件在某处……)。在 POSIX 层,用 _O_RDWR | 打开一个文件_O_TEXT 模式(如“r+”),需要查找到文件末尾以删除 CTRL+Z(如果存在)。这是来自 CRT 的 fopen 的引述文档:

Open in text (translated) mode. In this mode, CTRL+Z is interpreted as an end-of-file character on input. In files opened for reading/writing with "a+", fopen checks for a CTRL+Z at the end of the file and removes it, if possible. This is done because using fseek and ftell to move within a file that ends with a CTRL+Z, may cause fseek to behave improperly near the end of the file.

这里的问题是上面的检查调用了 32 位的 _lseek (请记住,sizeof long 在 64 位 Windows 上是 4 个字节,这与大多数其他 64 位平台不同),而不是 _lseeki64。显然,对于 11 GB 的文件,这会失败。具体来说,SetFilePointer失败,因为它被调用时使用 lpDistanceToMoveHighNULL 值。这是后一个调用的返回值和 LastErrorValue:

0:000> kc 2
Call Site
KERNELBASE!SetFilePointer
MSVCR90!lseek_nolock

0:000> r rax                       
rax=00000000ffffffff

0:000> dt _TEB @$teb LastErrorValue
ntdll!_TEB
   +0x068 LastErrorValue : 0x57

错误代码 0x57 是 ERROR_INVALID_PARAMETER .这是指 lpDistanceToMoveHigh 在尝试从大文件末尾开始搜索时为 NULL

要解决 CRT FILE 流的这个问题,我建议使用 io.open 打开文件。反而。这是 Python 3 的 I/O 堆栈的反向移植实现。它始终以原始二进制模式 (_O_BINARY) 打开文件,并在原始层之上实现自己的缓冲和文本模式层。

>>> import io                    
>>> f = io.open('a.csv', 'r+')
>>> f     
<_io.TextIOWrapper name='a.csv' encoding='cp1252'>
>>> f.buffer   
<_io.BufferedRandom name='a.csv'>
>>> f.buffer.raw
<_io.FileIO name='a.csv' mode='rb+'>
>>> f.seek(0, os.SEEK_END)
11811160064L

关于Python 无法在 r+ 模式下打开 11gb csv 但在 r 模式下打开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29729082/

相关文章:

python - Windows 多处理

windows - 如何从任务栏(XE4)隐藏 firemonkey 应用程序按钮?

java - 在文本文件中写入 "\n"

c - 读取文本文件时出错;行读取两次并且彼此有额外的换行符

python - XGBoost算法: Feature importance change after renaming columns

python - 如何告诉 cvxpy 如何对目标函数中矩阵的值求和?

Python-通过ftp获取文件的行数

windows - 插入后批准 USB 设备

java - 从内部 jar 中的类路径加载资源

python - pandas.dataframe 到orderedDictionary : using a passed argument to specify the key column name instead of explicitly writing it