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

Rob*_*inL 11 python windows file-io

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

我的代码在除了一个文件之外的所有文件上成功运行,这是11gb目录中最大的文件.第二大文件是4.5gb.

它失败的线条很简单:

with open(path_str,"r+") as my_file:
Run Code Online (Sandbox Code Playgroud)

我收到以下消息:

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

path_str我创建使用os.file.join以避免错误,我试图重命名文件,以a.csv公正,以确保有没有什么奇怪的文件名回事.这没有任何区别.

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

with open(path_str,"r") as my_file:
Run Code Online (Sandbox Code Playgroud)

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

有没有人知道Python可以处理的文件大小的限制或为什么我可能会收到此错误?我在Windows 7 64位上,有16GB的RAM.

Ery*_*Sun 19

Python 2中的默认I/O堆栈是通过CRT FILE流分层的.在Windows上,它们建立在使用文件描述符的POSIX仿真API之上(文件描述符又分层在用户模式Windows API上,该API分层在内核模式I/O系统上,它本身就是一个深层次的系统基于I/O请求数据包;硬件在某处......).在POSIX层中,使用_O_RDWR | _O_TEXT模式打开文件(如"r +"),需要搜索文件末尾以删除CTRL + Z(如果存在).以下是CRT fopen文档的引用:

以文本(翻译)模式打开.在此模式下,CTRL + Z被解释为输入时的文件结束字符.在用"a +"打开以进行读/写的文件中,fopen检查文件末尾的CTRL + Z并删除它,如果可能的话.这样做是因为使用fseek和ftell在以CTRL + Z结尾的文件中移动可能会导致fseek在文件末尾附近不正常地运行.

这里的问题是上面的检查调用32位_lseek(请记住sizeof long64位Windows上的4个字节,与大多数其他64位平台不同),而不是_lseeki64.显然这对于​​11 GB的文件来说是失败的.具体来说,SetFilePointer失败是因为它被调用了NULLlpDistanceToMoveHigh.这是返回值,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
Run Code Online (Sandbox Code Playgroud)

错误代码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
Run Code Online (Sandbox Code Playgroud)