You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中read后write写入位置不符预期:是特性还是Bug?

为什么以r+模式读取文件后直接write会写入末尾而非当前指针位置?

问题背景

在Python 3.11.2版本(运行于Windows 10 Home 22H2及MacOS 12.6.3系统)中,以r+模式打开文件并读取到中间位置后,直接调用file.write()时,写入位置是文件末尾而非当前指针位置,这与read()从当前位置继续读取的行为不符。

测试环境与内容

初始文件内容

content.txt初始内容:

this is just some miscellaneous unimportant text

测试代码

with open("content.txt", "r+", encoding="utf-8") as file:
    print("start tell", file.tell())

    a = file.read(20)
    a_tell = file.tell()
    print(f"{a=} {a_tell=}")

    b = file.read(5)
    b_tell = file.tell()
    print(f"{b=} {b_tell=}")

    file.write("ABCDE")
    abcde_tell = file.tell()
    print(f"{abcde_tell=}")

    file.seek(b_tell)
    print("seek b_tell", file.tell())

    file.write("XYZ")
    xyz_tell = file.tell()
    print(f"{xyz_tell=}")

代码输出

start tell 0
a='this is just some mi' a_tell=20
b='scell' b_tell=25
abcde_tell=53
seek b_tell 25
xyz_tell=28

结果对比

  • 预期文件内容:this is just some miscellXYZDEs unimportant text
  • 实际文件内容:this is just some miscellXYZous unimportant textABCDE

观察到的现象

  • file.read(n)后调用file.read(m)会从位置n开始读取,符合预期
  • file.read(n)后直接调用file.write("ABCDE")会写入文件末尾而非位置n,不符合直觉
  • 调用file.seek(n)后再执行file.write("XYZ")会在位置n写入,符合预期

原因分析

这是预期行为,并非Bug。Python的文件操作基于底层操作系统的C标准库实现,当在r+模式下混合读写操作时,遵循以下规则:

  • 当从读操作切换到写操作时,如果没有先调用seek()明确指定写入位置,操作系统会将文件指针移动到文件末尾再执行写入。这是因为读操作可能会在缓冲区留存未处理的数据,为了避免数据错乱,标准库强制将指针移至末尾,确保写入操作不会覆盖未读取的缓冲区内容。
  • 同理,从写操作切换到读操作时,也需要先调用seek()(除非是刚完成写入后立即读取,此时指针已在写入后的位置)。

在测试中,两次read()后指针停在位置25,但直接调用write()时,由于没有先执行seek(),系统自动将指针移到文件末尾(初始文件长度为48,写入5个字符后指针位置变为53),因此ABCDE被追加到了文件末尾。而调用seek(b_tell)明确指定位置后,写入操作就会在指定的位置25执行,覆盖原有内容。

解决方案

如果需要在读取后的当前指针位置写入,只需在write()前调用seek()将指针定位到当前位置即可,即使tell()显示指针已经在该位置:

# 在read()之后、write()之前添加
file.seek(file.tell())
file.write("ABCDE")

内容的提问来源于stack exchange,提问作者Katze2664

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 09:25:48