file.read()在2.7和3.3中返回不同的长度

时间:2014-02-20 08:06:51

标签: python python-2.7 python-3.x

我有一个二进制文件,

file = open(fname,"Ub")
len(file.read())

在Python 3.3中,它返回1279200,这是正确的。在Python 2.7中,它返回1279106。

这是怎么回事?可能的原因是什么?

在2.7中,如何获得1279200字节?

3 个答案:

答案 0 :(得分:1)

长话短说,Ub不会在一起。

Python 3遵循PEP-3116进行I / O实现。如果您查看open() implementation,您会注意到b使用Buffered*接口,而通用换行符则在TextIOWrapper中实现。因此,传递b只会禁用支持通用换行符的代码。

实际上,如果您尝试同时启用二进制模式和通用换行符,则open()的此实现甚至会失败。但是,此代码根本不支持U模式参数,只支持显式newline参数。

现在,我不知道为什么实际实现中的U不会触发错误。也许这只是一个遗漏,也许它是为了向后兼容。

现在,Python 2有两个I / O实现。如果您使用io.open(),则会获得与Python 3相同的行为。但是,您正在使用通过file type的C实现的遗留open()(相关代码:{{3 },open()field setting),此代码在二进制和文本文件支持之间没有明确的分离。因此,通用换行支持也适用于二进制文件。

因此,总结一下:您正在尝试使用两种冲突的文件模式。在Python 3中,这可能会触发错误,但不是出于某种原因。相反,b强于U而后者不起作用。在Python 2中,代码在二进制文件和文本文件之间没有明确的分割,bU都受到尊重,具体取决于上下文。


快速测试:

$ printf '1\n2\r\n3\n\r4\r5' > f
$ ipython3.3
In [1]: open('f', 'Ub').read()
Out[1]: b'1\n2\r\n3\n\r4\r5'

$ ipython2.7
In [1]: import io

In [2]: io.open('f', 'Ub').read()
Out[2]: '1\n2\r\n3\n\r4\r5'

In [3]: open('f', 'Ub').read()
Out[3]: '1\n2\n3\n\n4\n5'

答案 1 :(得分:0)

引用python文档:

  

提供“U”将文件作为文本文件打开,但行可以是   由以下任何一种终止:Unix的行尾约定   '\ n',Macintosh约定'\ r'或Windows约定'\ r \ n'。   所有这些外部表示都被Python视为'\ n'   程序。如果构建Python而没有通用换行符支持模式   'U'与普通文本模式相同。请注意文件对象   open也有一个名为newlines的属性,其值为   无(如果尚未看到换行符),'\ n','\ r','\ r \ n'或者a   包含所有新行类型的元组。

我建议您使用'rb'/'wb'模式,这有效!

答案 2 :(得分:0)

在Python 3中'U' mode is ignored

  

'U'模式已弃用,将在未来版本中引发异常    Python它在Python 3中没有效果。使用newline来控制    通用换行模式。

'b'以二进制模式打开文件,因此len(file.read())返回文件中的字节数(os.path.getsize(filename))。

在Python 2中'U''b' can be combined'b'设置f_binary flag(就我所见,对阅读没有影响)并传递给platform-specific fopen()(对Unix没有影响)。 'U'启用通用换行模式(\r\r\n转换为\n)。如果文件中有\r\n,它可能会改变读取字节数。