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深入学习之上下文管理器
Aug 31 Python
使用python存储网页上的图片实例
May 22 Python
python selenium firefox使用详解
Feb 26 Python
python实现简单加密解密机制
Mar 19 Python
详解利用python+opencv识别图片中的圆形(霍夫变换)
Jul 01 Python
python3图片文件批量重命名处理
Oct 31 Python
python系统指定文件的查找只输出目录下所有文件及文件夹
Jan 19 Python
python生成xml时规定dtd实例方法
Sep 21 Python
Python内置函数及功能简介汇总
Oct 13 Python
Python实现Kerberos用户的增删改查操作
Dec 14 Python
python 可视化库PyG2Plot的使用
Jan 21 Python
如何在C++中调用Python
May 21 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
Zend Framework入门教程之Zend_Db数据库操作详解
2016/12/08 PHP
Yii框架批量插入数据扩展类的简单实现方法
2017/05/23 PHP
JQuery实现用户名无刷新验证的小例子
2013/03/22 Javascript
jQuery防止click双击多次提交及传递动态函数或多参数
2014/04/02 Javascript
多种js图片预加载实现方式分享
2016/02/19 Javascript
Angularjs实现带查找筛选功能的select下拉框示例代码
2016/10/04 Javascript
JS实现图片上传预览功能
2016/11/21 Javascript
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
2016/12/15 Javascript
jquery做个日期选择适用于手机端示例
2017/01/10 Javascript
浅谈Vue2.0中v-for迭代语法的变化(key、index)
2018/03/06 Javascript
jquery插件开发模式实例详解
2019/07/20 jQuery
对layui数据表格动态cols(字段)动态变化详解
2019/10/25 Javascript
vue中touch和click共存的解决方式
2020/07/28 Javascript
浅析Python中的多进程与多线程的使用
2015/04/07 Python
Python实现把json格式转换成文本或sql文件
2015/07/10 Python
django商品分类及商品数据建模实例详解
2020/01/03 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
2020/02/24 Python
keras 权重保存和权重载入方式
2020/05/21 Python
如何利用python web框架做文件流下载的实现示例
2020/06/02 Python
python中selenium库的基本使用详解
2020/07/31 Python
python opencv pytesseract 验证码识别的实现
2020/08/28 Python
简单了解Python字典copy与赋值的区别
2020/09/16 Python
Python解析微信dat文件的方法
2020/11/30 Python
H5仿微信界面教程(一)
2017/07/05 HTML / CSS
YSL圣罗兰美妆美国官网:Yves Saint Lauret US
2016/11/21 全球购物
泰国第一在线超市:Tops
2021/02/13 全球购物
麦当劳辞职信范文
2014/01/18 职场文书
房屋租赁意向书
2014/04/01 职场文书
《青山处处埋忠骨》教学反思
2014/04/22 职场文书
办理护照工作证明
2014/10/10 职场文书
交警失职检讨书
2015/01/26 职场文书
介绍信样本
2015/01/31 职场文书
对领导班子的意见和建议
2015/06/08 职场文书
Python实现单例模式的5种方法
2021/06/15 Python
python面向对象版学生信息管理系统
2021/06/24 Python
Python实现GIF动图以及视频卡通化详解
2021/12/06 Python