file.seek() 在文本模式下基本不可用,因编码和换行符处理导致字节偏移不可预测,仅允许 seek(0);二进制模式(如'rb')才支持精确字节定位和全部whence参数。

file.seek() 在二进制模式下才能可靠定位字节偏移,这是由文本编码和换行符处理机制决定的 —— 文本模式下 seek() 的行为不可预测,甚至会直接报错。
为什么文本模式下 seek() 基本不能用
Python 的文本文件对象('r'、'w'、'a')内部做了缓冲和解码,指针位置不对应原始字节流。比如 UTF-8 编码中一个汉字占 3 字节,但 read(1) 只返回 1 个字符,seek(1) 却试图跳过 1 字节,结果可能落在某个汉字中间,触发 UnicodeDecodeError 或静默错位。
更关键的是:在文本模式下对 whence=1(相对当前位置)或 whence=2(文件末尾)调用 seek(),多数系统会直接抛出 io.UnsupportedOperation: can't do nonzero cur-relative seek。
- 只允许
seek(0)或seek(0, 0)(回到开头),其他偏移基本无效 -
seek()后若紧接着read()或write(),行为依赖底层 C 库,跨平台不一致 - 即使看似成功,后续读取内容也常与预期字节位置不符
二进制模式是唯一能精确控制字节偏移的场景
只有打开文件时指定 'rb'、'wb'、'r+b' 等二进制模式,seek() 才真正按字节操作,且 whence 三种值全部可用。
-
seek(100, 0):绝对定位到第 100 字节(从 0 开始计数) -
seek(-5, 1):从当前位置往回退 5 字节(必须在二进制模式) -
seek(-10, 2):定位到文件末尾前第 10 字节(常用于读取日志尾部)
注意:offset 必须是整数,负值仅在 whence=1 或 whence=2 下合法;在 whence=0 下传负数会引发 ValueError。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
立即学习“Python免费学习笔记(深入)”;
实际写入时容易忽略的同步问题
用 'r+b' 模式打开后,seek() 定位再 write() 是覆盖写入,不是插入 —— 这点很多人误以为能“插入”数据,其实只是把原位置字节替换成新字节,长度不变。
- 写入前必须
seek()到目标位置,否则默认从当前指针写 - 写入内容需是
bytes类型,f.write('hello'.encode()),不能直接传字符串 - 写入后若要继续读,需手动
seek()回读位置,Python 不自动重置指针 - 多线程/多进程并发修改同一文件时,
seek()+write()不是原子操作,需额外加锁
常见错误:用文本模式硬套二进制逻辑
最典型的翻车现场是:想读取大日志文件最后 1KB,写了 f.seek(-1024, 2),却用 open('log.txt', 'r') 打开 —— 直接报错或返回乱码。正确做法是 open('log.txt', 'rb'),读完再用 .decode('utf-8', errors='ignore') 处理。
- 不要指望
seek()在文本模式下“跳过前 N 行”,它跳的是字节,不是行 - 逐行读取(
for line in f:)和seek()是两种互斥的访问范式,混用极易出错 - Windows 下 CRLF 换行符会让文本模式的字节偏移更难估算,二进制模式则完全规避该问题
'rb' 或 'r+b'。文本模式下的 seek() 不是功能受限,而是设计上就不支持 —— 它根本不是为随机访问准备的。

















