Python使用multiprocessing多进程报错的一种情况解决方法

问题

Python使用multiprocessing进行多进程执行是常常会报各种奇怪的错误。比如使用tushare时会反复拉起pro_api,全局变量访问次数超过限制,进程帧读取权限报错等等。

分析

注意到一个问题,在这种情况下无论是报什么错误,往往是因为权限冲突或者反复调用。这意味着很多不应该被重复调用的工具被多次重复调用了。

在multiprocessing的官方文档中,我找到了这样一条提示:

Functionality within this package requires that the __main__ module be importable by the children. This is covered in Programming guidelines however it is worth pointing out here. This means that some examples, such as the multiprocessing.pool.Pool examples will not work in the interactive interpreter.

也就是说,在交互式环境中,我们应当使用main保护进程创建过程。但是实际上在验证时,未必有效。

在Stack Overflow中,我找到了这样一条说明:

On some systems, multiprocessing has to spawn a new copy of python and import your module to get to the worker code. Anything at module level is executed again... including the parent code that creates the pool. This would be an infinite recursion except python detects the problem and gives you a handy tip.

 也就是说,这是因为multiprocessing会复制整个Python进程环境来保证子进程能够工作,然后重新执行所有模块级的任务,如果创建进程的过程不受保护,就会形成无限递归。

解决方法 

综合上述两点,做出一个基本猜测:由于multiprocessing会复制整个父进程来保证子进程能够工作,那么创建进程的过程必须受到main的保护以避免子进程的进程池创建过程调用创建进程池的方法。那么在任何时候保证只在main空间能创建进程池即可。代码如下:

if __name__ == "__main__":
    with mp.Pool(10) as pool:
        use_function(pool, *args, **kwargs)

评价

这里往往报错的不会是multiprocessing,而且往往不止一个地方报错,因此会比较有迷惑性。我这次,同时出现了读取权限冲突、网络访问超限、程序拉起出错等错误。上在出现多重错误的时候就应该能想到可能问题不出在所有执行过程了,所以我首先检查了multiprocessing,但还是错过了,后来排查了一圈回来还是multiprocessing的嫌疑最大,只有这个模块我使用的懒人方法,里头的创建过程对我而言是完全黑箱的。

### 数据加载器多进程报错解决方案 当数据加载器在多进程环境下出现报错时,通常是因为程序试图在一个尚未完全初始化的进程中创建子进程。这种情况下,可以通过调整代码逻辑来解决问题。 以下是可能的解决方案: #### 1. 修改 `if __name__ == "__main__":` 的保护机制 为了防止在 Windows 或其他平台上因多进程模块的行为而导致错误,应始终将主入口函数放在 `if __name__ == "__main__":` 块中[^2]。这样可以确保只有在脚本作为主程序运行时才会执行特定代码。 ```python if __name__ == "__main__": # 主程序逻辑 pass ``` #### 2. 设置 PyTorch DataLoader 的 `num_workers` 如果使用的是 PyTorch 中的 `DataLoader`,可以通过减少或多增加 `num_workers` 参数的数量来进行调试。有时设置为 `0` 可以帮助定位问题所在,因为这会让主线程负责所有的数据加载工作。 ```python from torch.utils.data import DataLoader, Dataset class ExampleDataset(Dataset): def __getitem__(self, index): return ... data_loader = DataLoader(ExampleDataset(), batch_size=32, num_workers=0) ``` #### 3. 使用 `multiprocessing.set_start_method('spawn')` 对于某些平台(尤其是 macOS 和 Windows),默认的多进程启动方式可能会引发问题。通过显式指定 `set_start_method('spawn')` 来替代默认的方式,可以帮助规避此类问题。 ```python import multiprocessing as mp def worker_function(): pass if __name__ == '__main__': mp.set_start_method('spawn') pool = mp.Pool(processes=4) result = pool.map(worker_function, range(10)) ``` #### 4. 调整输入输出路径配置 如果是由于文件读取或写入路径不正确引起的错误,则需检查并修正这些路径。特别是在跨操作系统开发时,相对路径和绝对路径之间的差异可能导致意外行为[^3]。 ```python import os base_dir = '/path/to/data' file_path = os.path.join(base_dir, 'example.txt') with open(file_path, 'r') as f: data = f.read() ``` --- ### 总结 上述方法涵盖了从基础到高级的不同层次上的修复策略。具体采用哪种取决于实际应用场景以及所使用的框架版本等因素。务必逐一排查潜在因素,并结合实际情况灵活运用以上技巧。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值