Python使用多进程运行含有任意个参数的函数


Posted in Python onMay 02, 2020

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()

发现函数的参数是作为iter传进去的,但是我们现在有两个参数,自然想到使用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参数并没有被传进去:

Python使用多进程运行含有任意个参数的函数

那么如何传入多个参数呢?这也就是本文的重点,接着往下看吧。

2. 解决方案

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()

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()

在该库的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

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种方法!

以上这篇Python使用多进程运行含有任意个参数的函数就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 字典与字符串的互转实例
Jan 13 Python
使用Python向C语言的链接库传递数组、结构体、指针类型的数据
Jan 29 Python
利用python求积分的实例
Jul 03 Python
python 设置xlabel,ylabel 坐标轴字体大小,字体类型
Jul 23 Python
使用python动态生成波形曲线的实现
Dec 04 Python
Python +Selenium解决图片验证码登录或注册问题(推荐)
Feb 09 Python
Python根据指定文件生成XML的方法
Jun 29 Python
python利用递归方法实现求集合的幂集
Sep 07 Python
python上下文管理器异常问题解决方法
Feb 07 Python
Python语言内置数据类型
Feb 24 Python
python神经网络 使用Keras构建RNN训练
May 04 Python
Python使用pandas导入xlsx格式的excel文件内容操作代码
Dec 24 Python
python多进程使用函数封装实例
May 02 #Python
Python中使用filter过滤列表的一个小技巧分享
May 02 #Python
python同时遍历两个list用法说明
May 02 #Python
python多线程实现同时执行两个while循环的操作
May 02 #Python
python 实现两个线程交替执行
May 02 #Python
Python中使用threading.Event协调线程的运行详解
May 02 #Python
浅谈Python3多线程之间的执行顺序问题
May 02 #Python
You might like
深入php var_dump()函数的详解
2013/06/05 PHP
thinkPHP3.1验证码的简单实现方法
2016/04/22 PHP
谷歌浏览器 insertCell与appendChild的区别
2009/02/12 Javascript
TBCompressor js代码压缩
2011/01/05 Javascript
11个用于提高排版水平的基于jquery的文字效果插件
2012/09/14 Javascript
css transform 3D幻灯片特效实现步骤解读
2013/03/27 Javascript
js实现显示当前状态的导航效果代码
2015/08/28 Javascript
jQuery插件formValidator自定义函数扩展功能实例详解
2015/11/25 Javascript
Bootstrap Paginator分页插件与ajax相结合实现动态无刷新分页效果
2016/05/27 Javascript
javaScript生成支持中文带logo的二维码(jquery.qrcode.js)
2017/01/03 Javascript
巧用canvas
2017/01/21 Javascript
vue鼠标移入添加class样式,鼠标移出去除样式(active)实现方法
2018/08/22 Javascript
微信小程序签到功能
2018/10/31 Javascript
小程序登录态管理的方法示例
2018/11/13 Javascript
vue cli3 配置proxy代理无效的解决
2019/10/30 Javascript
[48:56]2018DOTA2亚洲邀请赛 3.31 小组赛 A组 VG vs KG
2018/03/31 DOTA
详解python 模拟豆瓣登录(豆瓣6.0)
2019/04/18 Python
PyQt5中向单元格添加控件的方法示例
2020/03/24 Python
Django返回HTML文件的实现方法
2020/09/17 Python
OpenCV灰度化之后图片为绿色的解决
2020/12/01 Python
python 解决函数返回return的问题
2020/12/05 Python
在css3中background-clip属性与background-origin属性的用法介绍
2012/11/13 HTML / CSS
CSS3 animation实现简易幻灯片轮播特效
2016/09/27 HTML / CSS
美国二手奢侈品寄售网站:TheRealReal
2016/10/29 全球购物
澳大利亚领先的在线礼品网站:Gifts Australia
2020/08/15 全球购物
编程实现去掉XML的重复结点
2014/05/28 面试题
linux面试题参考答案(7)
2012/10/29 面试题
介绍一下EJB的分类及其各自的功能及应用
2016/08/23 面试题
Ajax的优点和缺点
2014/11/21 面试题
党员违纪检讨书
2014/02/18 职场文书
四风问题对照检查整改措施思想报告
2014/10/05 职场文书
2016年5月份红领巾广播稿
2015/12/21 职场文书
教你如何使用Python Tkinter库制作记事本
2021/06/10 Python
mysql中int(3)和int(10)的数值范围是否相同
2021/10/16 MySQL
Nginx配置https的实现
2021/11/27 Servers
Python使用Opencv打开笔记本电脑摄像头报错解问题及解决
2022/06/21 Python