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

如何暂停ThreadPool执行指定函数后恢复,解决文件夹监控读文件权限报错问题

问题根因

你遇到的[Errno 13] Permission denied报错并非由监控线程占用文件夹导致,核心原因有三点:

  • 文件新增的通知触发时,将文件写入文件夹的程序还未完成写入操作、未释放文件锁,此时直接读取文件就会触发权限不足报错
  • 现有逻辑存在重复执行问题:你同时用thread_pool_executor.submit(self.process_csv)异步提交任务,又同步调用self.process_csv(),两个线程同时读取同一个文件也会触发锁冲突
  • 读取文件时使用了r+读写模式,该模式比只读的r模式要求更高的操作权限,也会提升权限报错概率
  • process_csv方法中硬编码了测试文件名,没有使用实际新增的文件路径,属于潜在逻辑缺陷
修复方案

方案1:等待文件锁释放(优先推荐,无需暂停监控)

不需要暂停监控线程,仅需增加文件可用性校验逻辑,等待文件锁释放后再读取即可,改动最小:

  1. 新增文件可用性校验工具方法:
def is_file_available(self, file_path, retry_count=5, wait_interval=1):
    # 重试5次,每次间隔1秒,判断文件是否可读
    for _ in range(retry_count):
        try:
            with open(file_path, 'r') as f:
                return True
        except PermissionError:
            time.sleep(wait_interval)
    return False
  1. 修改process_csv方法,接收动态传入的文件路径,先校验可用性再读取:
# 方法新增data_file参数,去掉硬编码的文件名
def process_csv(self, data_file):
    data_file_delimiter = ','
    largest_column_count = 0
    
    # 先判断文件是否可用
    if not self.is_file_available(data_file):
        print(f"文件{data_file}暂时无法访问,跳过处理")
        return

    # 把原代码的r+改为r只读模式
    with open(data_file, 'r') as temp_f:
        lines = temp_f.readlines()
        for l in lines:
            column_count = len(l.split(data_file_delimiter)) + 1
            largest_column_count = column_count if largest_column_count < column_count else largest_column_count
    column_names = [i for i in range(0, largest_column_count)]

    df = pd.read_csv(data_file,  delimiter=data_file_delimiter, names=column_names)
    df.fillna("", inplace=True)
    print(df)
  1. 修正文件处理位置的冗余逻辑,去掉重复调用:
if fType == ".csv" or fType == ".txt":
    data_file = a_string
    # 删掉原有的submit异步提交和重复的同步调用,二选一即可
    # 同步执行写法:
    self.process_csv(data_file)
    # 异步提交写法:thread_pool_executor.submit(self.process_csv, data_file)

方案2:暂停监控线程处理完成后恢复(符合你最初的需求)

如果确实需要暂停监控避免重复触发,可以通过标志位控制监控线程的运行状态:

  1. 在__init__方法中新增暂停标志位:
def __init__(self, parent, title):
    super(MainFrame, self).__init__(parent, title=title,size=(600,400))
    self.monitor_paused = False # 新增监控暂停标志位
    # 原有初始化逻辑不变
  1. 修改monitor_folder方法的循环逻辑,增加暂停判断:
while 1:
    # 新增暂停判断,暂停时跳过监听逻辑
    if self.monitor_paused:
        time.sleep(0.5)
        continue
    result = win32event.WaitForSingleObject (change_handle, 500)
    # 原有监听逻辑不变
  1. 文件处理位置增加暂停/恢复控制:
if fType == ".csv" or fType == ".txt":
    data_file = a_string
    self.monitor_paused = True # 暂停监控
    self.process_csv(data_file) # 同步处理文件
    self.monitor_paused = False # 处理完成恢复监控
附加优化建议

获取文件后缀不要用字符串切片,改用os.path.splitext(a_string)[1].lower(),可以避免文件名长度不足4位、后缀大写等异常情况,示例:

fType = os.path.splitext(a_string)[1].lower()
if fType == ".csv" or fType == ".txt":
    # 处理逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 20:30:02