seek() 的偏移量相对 whence 参数指定的位置:0 从开头、1 从当前、2 从末尾;文本模式仅支持 whence=0 且偏移非负,二进制模式才支持全功能。

seek() 的偏移量是相对谁算的?
不是相对文件开头,而是相对 whence 参数指定的位置。默认 whence=0(os.SEEK_SET)才从开头算;whence=1(os.SEEK_CUR)从当前位置算;whence=2(os.SEEK_END)从末尾算。很多人直接传一个正数,却没设 whence,结果在二进制模式下看似正常,在文本模式下可能出错——因为文本模式不支持 whence=1 或 whence=2(会抛 UnsupportedOperation)。
常见错误现象:io.UnsupportedOperation: can't do nonzero cur-relative seeks
- 文本模式(默认打开)只允许
whence=0,且偏移量必须是非负整数 - 想前后移动指针,必须用
rb或wb+等二进制模式打开文件 -
whence=2时,偏移量通常为负数(如f.seek(-10, 2)表示倒数第 10 字节)
tell() 返回的值到底代表什么?
tell() 返回的是当前读写位置的字节偏移量(从文件开头起),但这个值在文本模式下**不等于字符数**,尤其遇到多字节编码(如 UTF-8 中的中文)时。比如一个汉字占 3 字节,tell() 加了 3,但你只读了一个字符。
- 在
utf-8文本文件中,tell()值不能直接用于切分“第 N 个字符” - 只有二进制模式下,
tell()和seek()才严格一一对应、可逆 - 调用
tell()前,确保文件处于可定位状态(例如刚用read()读过,没发生缓冲区刷新或换行符转换干扰)
为什么 seek() 后 read() 有时读不到预期内容?
核心原因:文件指针移动后,缓冲区状态没同步。特别是用 open(..., buffering=...) 自定义缓冲,或在交互式环境(如 IPython)中多次 seek() + read(),容易读到旧缓存。
立即学习“Python免费学习笔记(深入)”;
- 调用
seek()后,如果之前有未读完的缓冲数据,Python 可能先返回缓存里剩下的,再真正去磁盘读 - 解决办法:在
seek()后加一次f.flush()(仅对写入有效),或更可靠地——关闭并重新打开文件,或使用f.seek(0, 2)强制刷新到末尾再回退 - 写入后立即
seek(0)想读取,必须先f.flush()且确保文件以+模式打开(如r+,w+)
跨平台处理大文件时 seek() 的边界注意点
Windows 下用文本模式打开文件,\r\n 被统一转成 \n,导致 tell() 返回的位置和实际字节位置不一致;Linux/macOS 不做此转换,但依然受编码影响。所以跨平台脚本若依赖精确字节定位,必须用二进制模式。
- 不要在文本模式下对
tell()结果做算术运算后传给seek(),尤其涉及换行符或非 ASCII 字符时 - 大文件中跳转到某“行号”,别靠反复
seek()+readline(),效率低还易错;改用内存映射(mmap)或逐行迭代 -
seek()到超出文件长度的位置不报错,但后续read()返回空字节;write()则会填充 \x00(稀疏文件行为,取决于 OS)
偏移量和当前位置的关系,本质是字节流上的标尺——这把尺子在文本模式下被编码和换行符悄悄掰弯了,而没人提醒你。










