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

Python多进程传递Process对象触发Pickling报错的解决方案

问题描述

在同一工作目录下创建了两个Python文件:

  • 业务模块script.py:包含一个持续循环运行、无法中途停止或暂停的函数,代码如下:
# script.py
def run():
    i = 0
    while True:
        print('\r', i, '\r', end='')
        i += 1
    
  • 自定义调试模块debugger.py:用于监听目录内文件更新,检测到变更时重启业务进程,代码如下:
# debugger.py
import os
import wait
from multiprocessing import Process, Queue

def capture_change(processesQueue):
    prev = os.path.getsize('wait.py')
    while True:
        curr = os.path.getsize('wait.py')

        if curr != prev:
            print('Changes Detected!!')
            process = processesQueue.get()
            process.kill()
            process.start()
            processesQueue.put(process)
        
        prev = curr

if __name__ == "__main__":
    processesQueue = Queue()
    p1 = Process(target= wait.run)
    processesQueue.put(p1)
    p2 = Process(target= capture_change, args= (processesQueue, ))

    p1.start()
    p2.start()

运行上述代码时抛出如下错误:

raise TypeError(
TypeError: Pickling an AuthenticationString object is disallowed for security reasons

尝试检索多种多进程间数据共享方案后,发现均不支持直接在进程间传递Process实例,需要可行的解决思路。

错误根因

报错的核心原因是设计逻辑存在问题:multiprocessing.Queue跨进程传递对象时,需要对对象做pickle序列化,而Process实例内部包含的AuthenticationString字段出于安全考虑是禁止被序列化的,因此跨进程传递Process实例本身就是不被Python支持的操作,不需要寻找能支持传递Process实例的跨进程通信方案,调整架构即可解决。

解决思路

核心原则:Process实例的生命周期管控(启动、杀掉、重启)必须在创建它的父进程中完成,不要跨进程传递Process对象。
具体实现逻辑:

  • 把文件变更检测的逻辑单独放在子进程中运行,检测到文件变更时,只需要通过Queue向主进程传递简单的可序列化信号(比如字符串RELOAD、布尔值True这类基础类型),不要传Process对象。
  • 主进程负责持有业务进程的实例,收到重启信号后,自主完成旧业务进程终止、业务模块重载、新业务进程启动的全流程。

修正后的debugger.py参考代码如下:

import os
import time
import script
from multiprocessing import Process, Queue

def capture_change(signal_queue):
    watch_file = "script.py"
    prev_mtime = os.path.getmtime(watch_file)
    while True:
        curr_mtime = os.path.getmtime(watch_file)
        if curr_mtime != prev_mtime:
            print("Changes Detected!!")
            signal_queue.put("RELOAD")
            prev_mtime = curr_mtime
        time.sleep(0.5) # 增加轮询间隔,避免CPU空转

if __name__ == "__main__":
    signal_queue = Queue()
    # 启动初始业务进程
    biz_process = Process(target=script.run)
    biz_process.start()
    # 启动文件监听进程
    watcher_process = Process(target=capture_change, args=(signal_queue,))
    watcher_process.daemon = True
    watcher_process.start()

    # 主进程循环处理信号,管控业务进程生命周期
    while True:
        sig = signal_queue.get()
        if sig == "RELOAD":
            # 终止旧业务进程
            if biz_process.is_alive():
                biz_process.kill()
                biz_process.join()
            # 重载业务模块,加载最新代码
            import importlib
            importlib.reload(script)
            # 启动新的业务进程
            biz_process = Process(target=script.run)
            biz_process.start()

额外注意事项:

  • 原代码存在笔误:业务模块文件名为script.py,但导入时写的是wait,运行前需要修正。
  • 文件变更检测建议用修改时间os.path.getmtime判断,不要仅判断文件大小,否则修改后文件大小不变的场景会漏检。
  • 文件轮询逻辑需要增加适当的sleep间隔,避免死循环空转占满CPU资源。

内容的提问来源于stack exchange,提问作者Aman Ahmed Siddiqui

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 02:09:24