Python使用concurrent.futures实现多线程优化STM原始数据转PNG疑问
修改建议
核心报错原因
你遇到的NameError: name 'root' is not defined是因为root/dirs/file是os.walk遍历过程中才会生成的局部变量,你没有先执行os.walk遍历就直接在executor.map中调用这些变量,属于未定义调用。
除此之外你的多线程改造还有多个逻辑问题:
- 多线程共享进程的工作目录,
os.chdir()在多线程环境下调用会导致所有线程的路径逻辑混乱,绝对不能这么用 - 任务拆分逻辑错误:你应该把耗时的单文件转换
data_conv作为并发执行的最小单元,而不是把整个目录遍历逻辑放到多线程中执行,反而会带来额外的路径冲突 - 原有代码变量命名混乱:
glob.glob("*.sm4")返回的就是文件名列表,不需要再嵌套for file in files循环,会把单个文件名拆成单个字符遍历,逻辑完全错误
正确改造步骤
- 先用单线程遍历所有目录,生成所有需要处理的
.sm4文件的完整输入路径、输出保存路径的参数列表,避免多线程操作目录的冲突 - 抽离单文件转换逻辑作为独立的线程执行函数,仅接收单文件处理所需的参数
- 所有路径用
os.path.join拼接,替代硬编码的路径分隔符和os.chdir操作 - 提交所有单文件转换任务到线程池并发执行
可运行的修改后代码示例
import os import glob import concurrent.futures # 请自行替换为你的原始数据根路径和输出保存根路径 RAW_ROOT = "/your/raw/data/path" SAVE_ROOT = "/your/output/save/path" def single_file_conv(raw_file_path, save_dir): # 单个文件转换逻辑,直接调用你原来的data_conv即可 # 这里参数根据你实际的data_conv要求调整 file_name = os.path.basename(raw_file_path) data_conv(raw_file_path, file_name, save_dir) if __name__ == "__main__": # 第一步:单线程遍历所有目录,收集所有待处理任务 task_list = [] for root, dirs, files in os.walk(RAW_ROOT): # 生成对应输出目录 rel_path = os.path.relpath(root, RAW_ROOT) save_dir = os.path.join(SAVE_ROOT, rel_path) os.makedirs(save_dir, exist_ok=True) # 收集当前目录下所有sm4文件的处理任务 for sm4_file in glob.glob(os.path.join(root, "*.sm4")): task_list.append((sm4_file, save_dir)) # 第二步:多线程并发执行转换任务 # 如果你是CPU密集型转换,把ThreadPoolExecutor换成ProcessPoolExecutor提速更明显 with concurrent.futures.ThreadPoolExecutor() as executor: # 解包参数提交任务 executor.map(lambda x: single_file_conv(*x), task_list)
额外说明
如果你的data_conv是计算密集型逻辑,Python多线程受GIL(全局解释器锁)限制提速效果有限,可以把上述代码中的ThreadPoolExecutor替换为ProcessPoolExecutor使用多进程执行,能获得更明显的提速效果。
内容的提问来源于stack exchange,提问作者user13058902
相关产品推荐
相关产品推荐

