Python多进程共享变量与结果获取的正确实现方式

竹里
竹里
发布时间:2026-10-13 | 6人浏览过
原创

本文详解Python中使用Multiprocessing库进行多进程编程时,如何正确共享变量并获取执行结果。重点解析Pool的使用方法及apply_async异步调用,深入探讨有界函数与无界函数的区别,指出多进程机制对类方法(有界函数)的Pickling限制,并提供将函数置于类外或转为静态方法的解决方案。

多进程共享变量和获得结果

出于工程实际需求,需要运行一个程序。虽然常听说Python的多线程存在全局解释器锁(GIL)的限制,效果类似“假多线程”,但考虑到任务间需要共享的参数较少,因此决定采用多进程方案。

经过查阅相关资料,实现多进程主要依赖Multiprocessing模块,该模块提供了两种主要方式:一种是直接使用Process类,另一种是使用Pool进程池。

p = Process(target=fun,args=(args))

通过调用p.start()可以启动一个子进程,随后使用p.join()方法阻塞父进程,直到子进程运行结束。

然而,这种方式较为繁琐,需要编写for循环来开启n个进程并逐个调用join,代码冗余度较高。

因此推荐使用Pool。它可以创建一个固定大小的进程池,每个进程通过调用apply_async()函数来执行指定的任务,最后再依次调用close()和join()方法完成资源清理和等待。

具体代码实现如下:

pathm=Manager().Queue(len(pathlist))
for d in pathlist:
 pathm.put(d)
p=Pool(cp.threads)
results=[]
for i in range(cp.threads):
 temp=p.apply_async(ProcessWorker,args=(i,pathm,cp))
 results.append(temp)
print 'Waiting for all subprocesses done...'
p.close()
p.join()
print 'All subprocesses finish Processing.'
results=[r.get() for r in results]

上述代码演示了如何使用Pool进行多进程处理,展示了在Pool中的进程间共享变量pathm的方法,以及如何获取进程函数的执行结果。需要特别注意,ProcessWorker必须是一个无界函数(即普通函数或静态方法),否则会因为无法被pickle序列化而报错,导致无法分配到各个进程中执行。

cPickle.PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

有界函数和Python的多进程机制

从上述示例引申出一个关键概念,即有界函数与无界函数的区别。

查阅相关资料后,总结如下:

有界函数是指封装在类中,且只有当类被实例化之后才能调用的函数,其“界”即为该类的实例。我们通常将这类带有self参数的函数称为类方法。

无界函数则是指未被封装在类中的普通函数,或者是类中的静态方法。它们与类本身相对独立,例如类中的静态方法,即使在某个类中定义,也不能访问类实例的参数和其他实例方法。

Python多进程的底层机制是将每个进程要调用的方法及其传入参数(如示例中的ProcessWorker)进行编译和打包,然后复制分发到各个子进程中执行。如果传入的是一个有界函数(类方法),其隐含参数是所属的类实例(包含属性和方法),但由于类实例的状态和引用关系复杂,往往难以正确打包和序列化。因此,Python限制了多进程调用的函数不能直接是类方法。

为了解决这一问题,我们需要将多进程调用的函数放置在类的外部,或者将其定义为静态函数。如果是静态函数,则不能通过self.ProcessWorker的形式在类内部调用,而需要在外部实例化类后调用,例如mc=MyClass(), mc.ProcessWorker(),或者直接通过MyClass().ProcessWorker()调用。

以上关于Python多进程共享变量及正确调用方式的介绍到此结束,希望能为读者提供参考,并欢迎大家继续支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表