ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python 3 tell()在追加读取模式下与文件指针不同步

2019-07-10 15:07:57  阅读:96  来源: 互联网

标签:python python-3-x


Python 2(2.7.15)不同,当打开二进制文件进行追加和读取时,我在Python 3(3.6.5)中看到了奇怪的f.tell()行为.如果当前搜索位置不在文件末尾时写入n个字节,则以下事情似乎按预期发生:

>文件指针移动到文件末尾.
>写入n个字节.
> n被添加到文件指针中.

但是,似乎f.tell()没有注意到步骤1,因此f.tell()返回的值与实际文件指针相比偏移了恒定的负数.我在Windows和Linux上都看到了相同的内容.

这里有一些Python 3代码演示了这个问题:

import io

# Create file with some content
f = open('myfile', 'wb')
f.write(b'abc')
print(f.tell())                 # 3
f.close()

# Now reopen file in append+read mode and check that appending works
f = open('myfile', 'a+b')
print(f.tell())                 # 3
f.write(b'def')                 # (Append)
print(f.tell())                 # 6

# Now seek to start of file and append again -> tell() gets out of sync!
print(f.seek(0))                # 0
print(f.tell())                 # 0
f.write(b'ghi')                 # (Append)
print(f.tell())                 # 3!!! (expected 9)
f.write(b'jkl')                 # (Append)
print(f.tell())                 # 6!!! (expected 12)

# Try calling seek without moving file pointer -> tell() starts working again
print(f.seek(0, io.SEEK_CUR))   # 12 (correct)
print(f.tell())                 # 12 (correct)

# Read whole file to verify its contents
print(f.seek(0))                # 0
print(f.read())                 # b'abcdefghijkl' (correct)
f.close()

Python 3文档有关于在文本文件上使用seek()/ tell()的警告(参见io.TextIOBase),以及关于某些平台上的追加模式的这一警告(参见open()):

[…] ‘a’ for appending (which on some Unix systems, means that all writes append to the end of the file regardless of the current seek position).

但我正在使用二进制文件,并且无论搜索位置如何,写入似乎都会附加到文件的末尾,因此我的问题不同.

我的问题:这种行为是在某个地方(直接或间接)记录下来的,还是至少记录了行为是未指定的?

编辑:

文本文件似乎没有这个问题(在Python 2和3中都没有),因此只有二进制文件不能按预期工作.

Python 3文档(io.TextIOBase)声明tell()为文本文件返回一个“不透明”值(即没有指定值如何表示该位置),并且因为没有提到这是否也适用于二进制文件文件,人们可能会推测我的问题与此不透明度有关.但是,这不可能是真的,因为即使是一个不透明的值必须 – 当给予seek()时 – 将文件指针返回到调用tell()时的位置,并在上面的示例中,当tell()返回第6个然后12在相同的文件位置(文件结束),只有seek(12)实际上会再次将文件指针移动到该位置.因此,值6不能通过文件指针不透明度来解释.

解决方法:

>调用f.seek(t,offset)时,将文件对象的位置更改为t offset
> written = f.write(data)按写入的字节前进位置
> f.tell()返回文件中的当前位置

所以,这里没有问题:

f.seek(0) # position = 0
f.write(b'123') # position += len(b'123') => position = 3
f.tell() # return position, which is equal to 3

并且数据是在当前位置之后立即写入的,因此在这种情况下您不会附加任何内容,而是覆盖现有数据.或者至少,你应该是,但这种行为可能会有所不同,正如你在文档中引用的那样.

标签:python,python-3-x
来源: https://codeday.me/bug/20190710/1425358.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有