从python 3中的文件末尾开始

时间:2014-12-20 16:38:50

标签: string python-3.x seek

python 3中的一个变化是删除了在正常文本模式下从文件末尾搜索的功能。什么是普遍接受的替代方案?

例如在python 2.7中,我将输入file.seek(-3,2)

我已经读过一些关于他们为什么这样做的内容,所以请不要只是链接到PEP。我知道使用' rb'将允许我寻找,但这使我的文本文件以错误的格式读取。

1 个答案:

答案 0 :(得分:6)

在Python 2中,文件数据在读取时未被解码。寻求向后和多字节编码不能很好地混合(你不知道下一个字符从哪里开始),这就是为Python 3禁用的原因。

你仍然可以通过TextIOBase.buffer attribute寻找底层缓冲区对象,但是你必须重新连接一个新的TextIOBase包装器,因为当前的包装器将会不再知道它在哪里:

import io

file.buffer.seek(-3, 2)
file = io.TextIOWrapper(
    file.buffer, encoding=file.encoding, errors=file.errors,
    newline=file.newlines)

我已将任何编码和线路处理信息复制到io.TextIOWrapper() object

考虑到这可能会破坏UTF-16,UTF-32,UTF-8和其他多字节编解码器。

演示:

>>> import io
>>> with open('demo.txt', 'w') as out:
...     out.write('Demonstration\nfor seeking from the end')
... 
38
>>> with open('demo.txt') as inf:
...     print(inf.readline())
...     inf.buffer.seek(-3, 2)
...     inf = io.TextIOWrapper(inf.buffer)
...     print(inf.readline())
... 
Demonstration

35
end

你可以将它包装在效用函数中:

import io

def textio_seek(fobj, amount, whence=0):
    fobj.buffer.seek(amount, whence)
    return io.TextIOWrapper(
        fobj.buffer, encoding=fobj.encoding, errors=fobj.errors,
        newline=fobj.newlines)

并将其用作:

with open(somefile) as file:
    # ...

    file = textio_seek(file, -2, 3)

    # ...

使用文件对象作为上下文管理器只是仍然有效,因为原始文件对象引用仍然附加到原始文件缓冲区对象,因此仍可用于关闭文件。