Python中ProcessPoolExecutor从头执行代码而非指定函数的问题
问题分析与解决方案
核心原因
在Windows系统中,concurrent.futures.ProcessPoolExecutor采用spawn机制创建子进程:每个子进程都会重新加载你的整个Python脚本。这就导致脚本中所有不在函数/类定义内的顶层代码(包括os.mkdir("output")),会被每一个子进程重复执行——多个进程同时尝试创建同一个output目录,自然会抛出「文件已存在」的错误。这不是concurrent.futures的Bug,而是跨平台多进程的标准行为。
修复步骤
1. 用if __name__ == '__main__':包裹主逻辑
这是Python多进程编程的必备写法,能确保只有主进程会执行初始化、创建进程池等操作,子进程导入脚本时会跳过这部分代码。
2. 修正代码中的其他错误
glob.glob("../project/temp/")无法匹配任何文件,需要改成glob.glob("../project/temp/*")(匹配目录下所有文件)- OpenCV处理后的灰度图是numpy数组,没有
save方法,需用cv2.imwrite完成保存 - 清理
output目录时,glob.glob("output")只能匹配目录本身,要改成glob.glob("output/*")来遍历目录内的文件
修正后的完整代码
import glob import concurrent.futures import cv2 import os def convert_this(filename): # 读取图片 img = cv2.imread(filename) if img is None: print(f"无法读取文件: {filename}") return # 转为灰度图 res = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 提取文件名,避免路径层级问题 basename = os.path.basename(filename) # 保存到output目录 cv2.imwrite(f"output/{basename}", res) if __name__ == '__main__': try: # 创建output目录(仅主进程执行),exist_ok=True避免目录已存在时报错 os.makedirs("output", exist_ok=True) with concurrent.futures.ProcessPoolExecutor() as executor: files = glob.glob("../project/temp/*") executor.map(convert_this, files) except Exception as e: print("Encountered Error!") print(e) # 清理output目录下的文件 filelist = glob.glob("output/*") for f in filelist: os.remove(f) # 仅当目录为空时删除 if not os.listdir("output"): os.rmdir("output")
内容的提问来源于stack exchange,提问作者rareguy
相关产品推荐
相关产品推荐

