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实现进程间通信简单实例
Jul 23 Python
Python中的choice()方法使用详解
May 15 Python
Python中操作符重载用法分析
Apr 29 Python
Python实现导出数据生成excel报表的方法示例
Jul 12 Python
python中实现指定时间调用函数示例代码
Sep 08 Python
Django使用Mysql数据库已经存在的数据表方法
May 27 Python
对pycharm代码整体左移和右移缩进快捷键的介绍
Jul 16 Python
Django高级编程之自定义Field实现多语言
Jul 02 Python
Python编写通讯录通过数据库存储实现模糊查询功能
Jul 18 Python
Python+OpenCV实现实时眼动追踪的示例代码
Nov 11 Python
Django Haystack 全文检索与关键词高亮的实现
Feb 17 Python
Python实现检测文件的MD5值来查找重复文件案例
Mar 12 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
深入探讨<br />和 \r\n两者有什么区别??
2013/06/05 PHP
php实现读取和写入tab分割的文件
2015/06/01 PHP
PHP+Mysql+jQuery查询和列表框选择操作实例讲解
2015/10/22 PHP
DWZ table的原生分页浅谈
2013/03/01 Javascript
iframe实用操作锦集
2014/04/22 Javascript
JavaScript和CSS交互的方法汇总
2014/12/02 Javascript
javascript控制台详解
2015/06/25 Javascript
不定义JQuery插件 不要说会JQuery
2016/03/07 Javascript
Node.js环境下JavaScript实现单链表与双链表结构
2016/06/12 Javascript
使用JavaScriptCore实现OC和JS交互详解
2017/03/28 Javascript
JS与jQuery实现子窗口获取父窗口元素值的方法
2017/04/17 jQuery
JavaScript之生成器_动力节点Java学院整理
2017/06/30 Javascript
浅谈Vue父子组件和非父子组件传值问题
2017/08/22 Javascript
js时间戳与日期格式之间转换详解
2017/12/11 Javascript
Vue组件通信之Bus的具体使用
2017/12/28 Javascript
如何在基于vue-cli的项目自定义打包环境
2018/11/10 Javascript
AjaxFileUpload.js实现异步上传文件功能
2019/04/19 Javascript
vue+element实现打印页面功能
2019/05/20 Javascript
node.js使用yargs处理命令行参数操作示例
2020/02/11 Javascript
利用python程序生成word和PDF文档的方法
2017/02/14 Python
Python错误提示:[Errno 24] Too many open files的分析与解决
2017/02/16 Python
python队列通信:rabbitMQ的使用(实例讲解)
2017/12/22 Python
python批量修改文件编码格式的方法
2018/05/31 Python
python对 MySQL 数据库进行增删改查的脚本
2020/10/22 Python
兰蔻法国官方网站:Lancôme法国
2020/02/22 全球购物
AssertionError 跟一下那个类是 “is – a”的关系
2012/02/21 面试题
2013年员工自我评价范文
2013/12/27 职场文书
政治思想表现评语
2014/05/04 职场文书
校园绿化美化方案
2014/06/08 职场文书
2014年个人委托书范本
2014/10/13 职场文书
恋恋笔记本观后感
2015/06/16 职场文书
解约证明模板
2015/06/19 职场文书
嘉年华活动新闻稿
2015/07/17 职场文书
巾帼建功标兵先进事迹材料
2016/02/29 职场文书
React配置子路由的实现
2021/06/03 Javascript
上个世纪50年代的可穿戴技术:无线电帽子
2022/02/18 无线电