如何判断.hdf5文件写入完成后调用,解决现有循环逻辑异常问题
问题根因分析
你当前代码的break逻辑本身没有问题,故障是其他逻辑缺陷导致的:
- 未初始化重试计数器:每次拿到新的队列事件时没有将
retry_count重置为0,前一个文件的重试次数会累加到新文件上,很快就会触发最大重试限制,导致文件直接被跳过。 - 异常分支无跳出逻辑:超过最大重试次数、捕获到非OSError异常的时候,都没有添加break跳出内层循环的逻辑,会导致内层死循环卡着当前文件,永远不会处理下一个队列任务。
- 队列任务未标记完成:如果你用的是Python标准库
queue.Queue,调用get()取任务后没有对应执行task_done(),会导致队列的join()逻辑永久阻塞,也可能引发后续任务处理异常。
修正后可运行代码
while True: event = self._q.get() retry_count = 0 # 每次处理新文件重置重试计数 process_success = False while retry_count < max_retry_count: try: # 检测文件是否完成写入(可正常读) with h5py.File(event.src_path, "r") as file: pass # 发射文件信号 self.new_file.emit(event.src_path, os.path.basename(event.src_path)) process_success = True break except OSError: retry_count += 1 print(f"h5文件 <{event.src_path}> 处于锁定状态,正在重试 {retry_count}/{max_retry_count}") time.sleep(retry_interval_seconds) except Exception as err: print(f"打开文件 <{event.src_path}> 时出现未预期错误 <{type(err).__name__}> ") traceback.print_exc() break # 非锁定类异常直接跳出不再重试 if not process_success: print(f"h5文件 <{event.src_path}> 达到最大重试次数或出现异常,已跳过") self._q.task_done() # 标记当前队列任务处理完成
额外优化建议
- 写入侧做标记更可靠:写入hdf5文件时先写后缀为
.tmp的临时文件,写完后再重命名为.h5后缀,监听侧只识别.h5后缀的文件,无需轮询重试就可以保证拿到的是写入完成的文件,比锁检测的稳定性高很多。 - 如果用的是
watchdog这类文件监听库,可以直接监听FileClosed事件替代轮询检测,减少不必要的IO开销。
内容的提问来源于stack exchange,提问作者mikanim
相关产品推荐
相关产品推荐

