Python多进程处理多参数函数的4种方案
本文探讨Python中multiprocessing库处理含多个参数的函数时的常见困境及解决方案。通过对比偏函数partial、可变参数包装、pathos库及内置starmap四种方法,详细解析各自实现原理与优缺点。推荐优先使用starmap,因其无需额外依赖且支持任意数量参数,适合高效并行计算场景。
问题引出
1. 问题引出
在实际开发中,程序运行效率至关重要,追求更快的执行速度是常态。针对Python语言,通常借助multiprocessing库来实现多进程并行处理,例如以下基础示例:
假设存在一个名为my_print的函数,其功能仅为打印传入的参数:
def my_print(x): print(x)
若觉得单进程执行速度无法满足需求,可尝试将其改造为多进程模式:
from multiprocessing import Pool
def my_print(x):
print(x)
if __name__ == "__main__":
x = [1, 2, 3, 4, 5]
pool = Pool()
pool.map(my_print, x)
pool.close()
pool.join()
上述方式在单参数场景下能显著提升速度,但若函数参数不止一个x,而是包含多个参数,直接套用上述代码是否可行?例如,my_print函数新增参数y:
def my_print(x, y): print(x + y)
查阅Pool类中map方法的文档说明:
def map(self, func, iterable, chunksize=None):
'''
Apply `func` to each element in `iterable`, collecting the results
in a list that is returned.
'''
return self._map_async(func, iterable, mapstar, chunksize).get()
可以看到,map函数的第二个参数iterable接收的是单个可迭代对象。面对多参数情况,直观想法是使用zip函数将多个参数列表打包组合:
if __name__ == "__main__":
x = [1, 2, 3, 4, 5]
y = [1, 1, 1, 1, 1]
zip_args = list(zip(x, y))
pool = Pool()
pool.map(my_print, zip_args)
pool.close()
pool.join()
然而实际执行后发现,y参数并未被正确传递至目标函数:

那么,如何正确向多进程函数传递多个参数?这正是本文要解决的核心问题,请继续阅读后续内容。
解决方案
2. 解决方案
使用偏函数(partial)
2.1 使用偏函数(partial)
偏函数的概念类似于数学中的偏导数,允许我们在调用时固定部分参数,仅关注剩余变量的变化。在前述例子中,若y始终固定为1,则在传入参数时只需考虑x的变化即可。
例如,假设有一个函数接收两个参数a和b,其中a代表不同路径下的图片文件路径,b代表输出保存路径。显然,a是动态变化的,而为了将所有图片保存至同一文件夹,b通常保持不变。
具体实现如下:
if __name__ == '__main__':# 多线程,多参数,partial版本
x = [1, 2, 3, 4, 5]
y = 1
partial_func = partial(my_print, y=y)
pool = Pool()
pool.map(partial_func, x)
pool.close()
pool.join()
使用可变参数
2.2 使用可变参数
Python函数支持定义可变参数。所谓可变参数,即传入的参数个数不固定,可以是1个、2个或任意多个。基于此特性,我们可以构造一个包装函数来接收打包后的参数。具体实现如下:
def multi_wrapper(args):
return my_print(*args)
def my_print(x, y):
print(x + y)
if __name__ == "__main__": # 多线程,多参数,可变参数版本
x = [1, 2, 3, 4, 5]
y = [1, 1, 1, 1, 1]
zip_args = list(zip(x, y))
pool = Pool()
pool.map(multi_wrapper, zip_args)
pool.close()
pool.join()
使用pathos提供的多进程库
2.3 使用pathos提供的多进程库
from pathos.multiprocessing import ProcessingPool as newPool
if __name__ == '__main__':# 多线程,多参数,pathos版本
x = [1, 2, 3, 4, 5]
y = [1, 1, 1, 1, 1]
pool = newPool()
pool.map(my_print, x, y)
pool.close()
pool.join()
pathos库中的map函数允许直接输入多个参数列表,其底层实现同样利用了可变参数机制。具体代码如下:
def map(self, f, *args, **kwds):
AbstractWorkerPool._AbstractWorkerPool__map(self, f, *args, **kwds)
_pool = self._serve()
return _pool.map(star(f), zip(*args)) # chunksize
使用starmap函数
2.4 使用starmap函数
if __name__ == '__main__': # 多线程,多参数,starmap版本
x = [1, 2, 3, 4, 5]
y = [1, 1, 1, 1, 1]
zip_args = list(zip(x, y))
pool = Pool()
pool.starmap(my_print, zip_args)
pool.close()
pool.join()
总结
3. 总结
综上所述,上述4种实现方式中,第1种(偏函数)限制较多,若函数其他参数也动态变化,则适用性较差。其余三种方法在体验上依次提升,均支持任意数量参数输入。但第2种方法需额外编写包装函数,略显繁琐;第3种方法需额外安装pathos第三方包;而第4种方法无需任何额外依赖即可完成,因此推荐优先选择第4种方法。
以上关于Python多进程处理含任意参数函数的内容分享完毕,希望能对大家有所帮助。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













