10

file.read()上的 Python 文档指出An empty string is returned when EOF is encountered immediately.该文档进一步指出:

请注意,此方法可能会多次调用底层 C 函数 fread() 以获取尽可能接近 size 的字节。另请注意,在非阻塞模式下,即使没有给出大小参数,返回的数据也可能少于请求的数据。

我相信 Guido 已经表达了他对不添加 f.eof() 完全清晰的观点,因此需要使用 Python 方式!

但是,我不清楚的是,如果您从读取中收到的字节数少于请求的字节数,但您确实收到了一些字节,那么您是否已达到 EOF 是一个确定的测试。

IE:

with open(filename,'rb') as f:
    while True:
        s=f.read(size)
        l=len(s) 
        if l==0: 
            break     # it is clear that this is EOF...
        if l<size:
            break      # ? Is receiving less than the request EOF???

break如果您收到的字节数少于调用中请求的字节数,这是否是一个潜在的错误file.read(size)

4

2 回答 2

23

你不是带着蛇皮思考...... Python不是C。

首先,回顾:

  • st=f.read() 读取到 EOF,或者如果作为二进制文件打开,则读取到最后一个字节;
  • st=f.read(n)尝试读取n字节,在任何情况下都不会超过n字节;
  • st=f.readline() 一次读取一行,该行以 '\n' 或 EOF 结尾;
  • st=f.readlines() 使用 readline() 读取文件中的所有行并返回行列表。

如果文件读取方法位于 EOF,则返回''. 相同类型的 EOF 测试用于其他“类似文件”的方法,如 StringIO、socket.makefile 等。返回小于n字节的 fromf.read(n)肯定不是对 EOF 的决定性测试!虽然该代码可能工作 99.99%时间,这是它不起作用的时间,找到它会非常令人沮丧。另外,它是糟糕的 Python 形式。n在这种情况下,唯一的用途是为返回的大小设置一个上限。

Python 类文件方法返回少于n字节的一些原因是什么?

  1. EOF 当然是一个常见的原因;
  2. 网络套接字可能在读取时超时但仍保持打开状态;
  3. 确切n的字节可能会导致逻辑多字节字符(例如\r\n在文本模式中,我认为是 Unicode 中的多字节字符)或您不知道的某些底层数据结构之间的中断;
  4. 该文件处于非阻塞模式,另一个进程开始访问该文件;
  5. 暂时无法访问该文件;
  6. 文件、磁盘、网络等上的潜在错误条件,可能是临时的。
  7. 程序收到了一个信号,但信号处理程序忽略了它。

我会以这种方式重写你的代码:

with open(filename,'rb') as f:
    while True:
        s=f.read(max_size)
        if not s: break

        # process the data in s...

或者,编写一个生成器

def blocks(infile, bufsize=1024):
    while True:
        try:
            data=infile.read(bufsize)
            if data:
                yield data
            else:
                break
        except IOError as (errno, strerror):
            print "I/O error({0}): {1}".format(errno, strerror)
            break

f=open('somefile','rb')

for block in blocks(f,2**16):
    # process a block that COULD be up to 65,536 bytes long
于 2010-12-13T21:48:28.210 回答
1

以下是我的 C 编译器文档对该fread()函数的说明:

size_t fread( 
   void *buffer,
   size_t size,
   size_t count,
   FILE *stream 
);

fread返回实际读取的完整项目数,如果发生错误或在达到 count 之前遇到文件末尾,则可能小于 count。

因此,看起来小于size意味着发生了错误或已达到 EOF——因此break退出循环将是正确的做法。

于 2010-12-13T08:37:00.940 回答