网络驱动器加载数据偶发PermissionError,求更优异常处理方案
优化网络驱动器数据加载的PermissionError处理方案
针对网络驱动器加载数据时偶发的PermissionError,以下是几个更稳定高效的优化方案:
1. 带指数退避与次数限制的重试逻辑
原方案仅重试一次且固定等待10秒,既可能因等待时间过长浪费资源,也可能因重试次数不足仍触发失败。改用指数退避+重试次数限制的逻辑,能更适配网络临时波动的场景:
import time def load_data_with_retry(self, path, max_retries=3, initial_delay=1): retries = 0 while retries < max_retries: try: return self.data_file_loader(path) except PermissionError: retries += 1 if retries == max_retries: # 超过最大重试次数,抛出原异常以便上层处理 raise # 指数退避:重试间隔依次为1s、2s、4s...避免频繁请求加重网络负担 delay = initial_delay * (2 ** (retries - 1)) print(f"加载路径 {path} 遇PermissionError,{delay}秒后重试(第{retries}次)") time.sleep(delay)
优势:
- 指数增长的等待间隔,给网络驱动器足够的恢复时间,同时避免不必要的长时间等待
- 限制最大重试次数,防止因持续异常导致脚本无限挂起
2. 扩大异常捕获范围(按需)
网络驱动器的PermissionError有时可能是临时连接中断、资源忙等问题的表象,而非真正的权限不足。可以针对性捕获更多网络/IO相关异常:
# 示例:捕获PermissionError及常见网络IO异常 def load_data_with_retry(self, path, max_retries=3, initial_delay=1): retries = 0 while retries < max_retries: try: return self.data_file_loader(path) except (PermissionError, OSError) as e: # 可根据错误码进一步筛选,比如Windows下网络相关错误码 if hasattr(e, 'errno') and e.errno in (13, 10054, 10060): retries += 1 if retries == max_retries: raise delay = initial_delay * (2 ** (retries - 1)) print(f"加载路径 {path} 遇IO异常[{e.errno}],{delay}秒后重试(第{retries}次)") time.sleep(delay) else: # 非目标异常,直接抛出 raise
3. 批量加载时控制并发数
遍历大型数据集时,若同时发起大量网络IO请求,可能导致网络驱动器资源过载,触发PermissionError。此时需限制并发加载的数量:
from concurrent.futures import ThreadPoolExecutor # 示例:用线程池控制并发数,避免网络过载 def batch_load_data(self, paths, max_workers=4): with ThreadPoolExecutor(max_workers=max_workers) as executor: # 用上面的重试函数作为加载逻辑 results = list(executor.map(lambda p: self.load_data_with_retry(p), paths)) return results
4. 预缓存数据到本地(终极方案)
如果数据集允许,优先将网络驱动器上的文件批量同步到本地磁盘,再从本地加载数据,彻底规避网络波动带来的问题:
import shutil import os def sync_network_data_to_local(network_path, local_path): if not os.path.exists(local_path): os.makedirs(local_path) # 递归同步目录(根据需求调整,比如只同步特定后缀文件) for root, dirs, files in os.walk(network_path): local_root = root.replace(network_path, local_path) if not os.path.exists(local_root): os.makedirs(local_root) for file in files: src = os.path.join(root, file) dst = os.path.join(local_root, file) # 仅同步本地不存在或更新的文件 if not os.path.exists(dst) or os.path.getmtime(src) > os.path.getmtime(dst): shutil.copy2(src, dst) # 先同步,再从本地加载 sync_network_data_to_local(r"\\network-drive\dataset", "./local_dataset") data = self.data_file_loader("./local_dataset/file.txt")
内容的提问来源于stack exchange,提问作者Zack_Aria
相关产品推荐
相关产品推荐

