如何在不使用if __name__ == '__main__'的情况下执行multiprocessing Pool
问题分析与解决
首先,你的代码存在几处语法和逻辑错误,先修正:
import os from pathlib import Path import pandas as pd from multiprocessing import Pool def process_file(filename): path = "C:\\Users\\siya\\Desktop\\data" if filename.endswith('.xlsm'): file_path = Path(os.path.join(path, filename)) sheet = pd.read_excel(file_path, 'sheetname', index_col=False) print(sheet) def func_process(): path = "C:\\Users\\siya\\Desktop\\data" with Pool(processes=12) as pool: filenames = os.listdir(path) pool.map(process_file, filenames) # 直接调用在Windows会报错,Linux/WSL可正常运行 func_process()
为什么Windows下会报错?
Windows系统中,multiprocessing默认使用spawn启动子进程。这种方式会重新导入主模块来初始化子进程环境,导致模块顶层的func_process()调用在子进程中被重复执行,进而递归创建新进程,触发RuntimeError。
不使用if __name__ == '__main__'的可行方案
方案1:切换到Linux/WSL环境
Linux系统默认使用fork启动子进程,fork会直接复制父进程的内存空间,不会重新导入主模块。因此在Linux或Windows的WSL子系统中,上述修正后的代码可以直接运行,无需添加if __name__ == '__main__'判断。
方案2:使用forkserver启动方式(仅部分场景可行)
可以强制使用forkserver启动子进程,这种方式会先启动一个独立的服务器进程,后续子进程都从该服务器进程fork出来,避免重复导入主模块。示例如下:
import os from pathlib import Path import pandas as pd from multiprocessing import Pool, set_start_method def process_file(filename): path = "C:\\Users\\siya\\Desktop\\data" if filename.endswith('.xlsm'): file_path = Path(os.path.join(path, filename)) sheet = pd.read_excel(file_path, 'sheetname', index_col=False) print(sheet) def func_process(): path = "C:\\Users\\siya\\Desktop\\data" with Pool(processes=12) as pool: filenames = os.listdir(path) pool.map(process_file, filenames) # 设置启动方式,仅需执行一次 try: set_start_method('forkserver') except RuntimeError: # 若已设置过则忽略 pass func_process()
注意:forkserver在Windows上的支持有限,部分Python环境可能无法正常工作,且仍存在一定概率触发递归执行问题。
结论
在原生Windows环境中,完全避开if __name__ == '__main__'几乎不可能,这是Python multiprocessing模块在Windows平台的机制限制。最稳妥的方式还是遵循官方推荐的写法,添加if __name__ == '__main__'判断:
import os from pathlib import Path import pandas as pd from multiprocessing import Pool def process_file(filename): path = "C:\\Users\\siya\\Desktop\\data" if filename.endswith('.xlsm'): file_path = Path(os.path.join(path, filename)) sheet = pd.read_excel(file_path, 'sheetname', index_col=False) print(sheet) def func_process(): path = "C:\\Users\\siya\\Desktop\\data" with Pool(processes=12) as pool: filenames = os.listdir(path) pool.map(process_file, filenames) if __name__ == '__main__': func_process()
内容的提问来源于stack exchange,提问作者Siya chandran
相关产品推荐
相关产品推荐

