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使用scrapy解析js示例
Jan 23 Python
回调函数的意义以及python实现实例
Jun 20 Python
pycharm运行程序时在Python console窗口中运行的方法
Dec 03 Python
Python3中_(下划线)和__(双下划线)的用途和区别
Apr 26 Python
解决Django中调用keras的模型出现的问题
Aug 07 Python
python爬虫 猫眼电影和电影天堂数据csv和mysql存储过程解析
Sep 05 Python
Python django框架输入汉字,数字,字符生成二维码实现详解
Sep 24 Python
Python数据持久化存储实现方法分析
Dec 21 Python
python实现跨excel sheet复制代码实例
Mar 03 Python
使用python实现下载我们想听的歌曲,速度超快
Jul 09 Python
python 简单的调用有道翻译
Nov 25 Python
matplotlib常见函数之plt.rcParams、matshow的使用(坐标轴设置)
Jan 05 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 XML操作类DOMDocument
2009/12/16 PHP
对google个性主页的拖拽效果的js的完整注释[转]
2007/04/10 Javascript
开发 Internet Explorer 右键功能表(ContextMenu)
2013/07/03 Javascript
MyEclipse取消验证Js的两种方法
2013/11/14 Javascript
jquery对ajax的支持介绍
2013/12/10 Javascript
javascript避免数字计算精度误差的方法详解
2014/03/05 Javascript
js中数组排序sort方法的原理分析
2014/11/20 Javascript
javascript实现倒计时(精确到秒)
2015/06/26 Javascript
jQuery获取radio选中项的值实例
2016/06/18 Javascript
jQuery元素选择器实例代码
2017/02/06 Javascript
详解用webpack的CommonsChunkPlugin提取公共代码的3种方式
2017/11/09 Javascript
vue实现样式之间的切换及vue动态样式的实现方法
2017/12/19 Javascript
详解使用React进行组件库开发
2018/02/06 Javascript
JavaScript监听触摸事件代码实例
2019/12/30 Javascript
javascript实现前端成语点击验证
2020/06/24 Javascript
Python中转换角度为弧度的radians()方法
2015/05/18 Python
每天迁移MySQL历史数据到历史库Python脚本
2018/04/13 Python
django之跨表查询及添加记录的示例代码
2018/10/16 Python
解决python3 Pycharm上连接数据库时报错的问题
2018/12/03 Python
在django view中给form传入参数的例子
2019/07/19 Python
Python3 使用pillow库生成随机验证码
2019/08/26 Python
python matplotlib实现将图例放在图外
2020/04/17 Python
皇家阿尔伯特瓷器美国官网:Royal Albert美国
2020/02/16 全球购物
文史专业毕业生自荐信
2013/11/17 职场文书
大学生收银员求职信分享
2014/01/02 职场文书
小学毕业感言150字
2014/02/05 职场文书
公司中层干部的自我评价分享
2014/03/01 职场文书
数学教育专业求职信
2014/07/22 职场文书
乡镇2014法制宣传日活动总结
2014/11/01 职场文书
小学教师师德师风承诺书
2015/04/28 职场文书
解决go在函数退出后子协程的退出问题
2021/04/30 Golang
Java使用Unsafe类的示例详解
2021/09/25 Java/Android
SQL Server2019数据库备份与还原脚本,数据库可批量备份
2021/11/20 SQL Server
如何创建一个创建MySQL数据库中的datetime类型
2022/03/21 MySQL
vscode内网访问服务器的方法
2022/06/28 Servers
mysql拆分字符串作为查询条件的示例代码
2022/07/07 MySQL