You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu下Python multiprocessing僵尸进程及Reactor报错如何解决?

初始手动管理Process出现僵尸进程的解决方案

出现僵尸进程的核心原因是你只在所有任务分发完成后才统一执行join()回收进程,运行过程中替换已结束进程时没有回收旧进程的退出状态,导致结束的子进程变为僵尸进程残留。可通过以下方式预防:

  • 替换非存活进程前先执行join()回收资源,修改process_x函数中的进程创建逻辑:
    if not (list_process[i] and list_process[i].is_alive()):
        # 先回收已结束的旧进程
        if list_process[i] is not None:
            list_process[i].join()
        list_process[i] = Process(target=launch_crawler, args=(SalesSpider, urls_lst.pop(0)), daemon=True)
        list_process[i].start()
        break
    
  • 创建进程时添加daemon=True参数,设置子进程为守护进程,主进程退出时会自动强制回收所有子进程,避免残留。
  • 移除手动del对象和gc.collect()调用,Python自动内存管理足够应对该场景,频繁主动调用GC反而会降低运行性能。
  • 降低进程数量,Scrapy本身是异步IO框架,单进程即可处理大量并发请求,开120个进程会导致严重的上下文切换和资源竞争,反而降低稳定性,建议进程数设置为CPU核心数的1~2倍即可。
Pool方案出现ReactorNotRestartable错误的解决方案

该错误的原因是multiprocessing.Pool默认会复用工作进程,Twisted的Reactor是单例模式,同一个进程内只能启动一次,第一个任务跑完Reactor停止后,第二个任务复用同一个进程再次启动Reactor就会触发该报错。可通过以下方式解决:

  • 最简单的方案是设置工作进程只处理1个任务就销毁,创建Pool时添加maxtasksperchild=1参数:
    pool = multiprocessing.Pool(processes, maxtasksperchild=1)
    
    每个工作进程只跑一个任务就退出,新任务会用全新的进程启动Reactor,不会出现重启问题。
  • 更高性能的方案是每个工作进程仅启动一次Reactor,批量处理多个任务,修改任务函数为接收一批seller统一执行:
    def launch_crawler_batch(sellers_batch):
        process = CrawlerProcess(crawler_settings)
        for seller in sellers_batch:
            formated_seller = format_target(seller[1])
            if formated_seller:
                process.crawl(SalesSpider, seller[0], formated_seller, seller[2])
        process.start(stop_after_crawl=True)
    
    调用时提前将seller列表按批次拆分后传入Pool即可,每个进程仅启动一次Reactor,避免重复创建的开销。
  • 最优方案是直接使用Scrapy自带的并发能力,调整CONCURRENT_REQUESTS参数提高单进程并发数,不需要额外引入多进程管理,架构更简单稳定性也更高。

内容的提问来源于stack exchange,提问作者IndiaSke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 12:45:03