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

线程中io.open的readline函数异常:文件增大但读取空行

文件尾部监听时readline返回空的问题解决

问题原因

你的代码出现这种情况,核心原因有两个:

  1. 文件对象无法感知外部修改:用seek(0,2)定位到文件末尾后,文件对象的内部指针停在该位置,外部程序追加内容后,文件对象不会自动更新状态,readline()会直接返回空字符串。
  2. 缓冲同步问题:外部程序写入时可能使用系统缓冲,内容未立即刷新到磁盘;os.path.getsize()读取的是磁盘文件大小,但文件对象的缓冲区未同步这个变化。

修正后的代码

下面是调整后的实现,主动检查文件大小变化并同步读取新内容:

import io
import os
import time

with io.open(file_path, 'r', encoding='utf-8') as file:
    # 初始化当前指针位置到文件末尾
    current_pos = file.seek(0, 2)
    while not self._stop_event.is_set():
        # 通过文件描述符获取文件实际大小(比os.path.getsize更可靠)
        file_size = os.fstat(file.fileno()).st_size
        
        if file_size > current_pos:
            # 移动指针到上次读取的位置,避免重复读取
            file.seek(current_pos)
            # 读取所有新增内容并按行处理
            for line in file:
                print(f"LINE : {line.strip()}")
            # 更新指针位置到当前文件末尾
            current_pos = file.tell()
        else:
            print(f"NO NEW CONTENT - FILE SIZE = {file_size}")
            time.sleep(1)

额外处理:无换行符的写入场景

如果外部程序追加的内容可能没有以换行符结尾,readline()会一直等待换行符导致无法返回。这种情况下可以改用读取全部新增内容再分割:

# 替换读取部分的代码
if file_size > current_pos:
    file.seek(current_pos)
    # 读取所有新增内容
    new_content = file.read()
    if new_content:
        # 按行分割,兼容无结尾换行的情况
        for line in new_content.splitlines():
            print(f"LINE : {line.strip()}")
    current_pos = file.tell()

关键优化点

  • 使用os.fstat(file.fileno()).st_size直接通过文件描述符获取大小,避免路径解析和系统缓存带来的不一致。
  • 通过对比current_pos和文件大小,主动触发新内容的读取,而非依赖readline()的被动检测。
  • 每次读取后更新指针位置,确保不会重复读取旧内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 18:35:25