参考链接: Python的惊人技巧

Python的并发处理能力臭名昭著。先撇开线程以及GIL方面的问题不说,我觉得多线程问题的根源不在技术上而在于理念。大部分关于Pyhon线程和多进程的资料虽然都很不错,但却过于细节。这些资料讲的都是虎头蛇尾,到了真正实际使用的部分却草草结束了。

传统例子

在DDG https://duckduckgo.com/ 搜索“Python threading tutorial”关键字,结果基本上却都是相同的类+队列的示例。

标准线程多进程,生产者/消费者示例:

这里是代码截图,如果用其他模式贴出大段代码会很不美观。文本模式点这里 here

Mmm.. 感觉像是java代码

在此我不想印证采用生产者/消费者模式来处理线程/多进程是错误的— 确实没问题。实际上这也是解决很多问题的最佳选择。但是,我却不认为这是日常工作中常用的方式。

问题所在

一开始,你需要一个执行下面操作的铺垫类。接着,你需要创建一个传递对象的队列,并在队列两端实时监听以完成任务。(很有可能需要两个队列互相通信或者存储数据)

Worker越多,问题越大.

下一步,你可能会考虑把这些worker放入一个线程池一边提高Python的处理速度。下面是

IBM tutorial 上关于线程较好的示例代码。这是大家常用到的利用多线程处理web页面的场景

Seriously, Medium. Fix your code support. Code is Here.

感觉效果应该很好,但是看看这些代码!初始化方法、线程跟踪,最糟的是,如果你也和我一样是个容易犯死锁问题的人,这里的join语句就要出错了。这样就开始变得更加复杂了!

到现在为止都做了些什么?基本上没什么。上面的代码都是些基础功能,而且很容易出错。(天啊,我忘了写上在队列对象上调用task_done()方法(我懒得修复这个问题在重新截图)),这真是性价比太低。所幸的是,我们有更好的办法.

引入:Map

Map 是个很酷的小功能,也是简化Python并发代码的关键。对那些不太熟悉Map的来说,它有点类似Lisp.它就是序列化的功能映射功能. e.g.

urls = [', ']

results = map(urllib2.urlopen, urls)

这里调用urlopen方法,并把之前的调用结果全都返回并按顺序存储到一个集合中。这有点类似

results = []

for url in urls:

results.append(urllib2.urlopen(url))

Map能够处理集合按顺序遍历,最终将调用产生的结果保存在一个简单的集合当中。

为什么要提到它?因为在引入需要的包文件后,Map能大大简化并发的复杂度!

支持Map并发的包文件有两个:

Multiprocessing,还有少为人知的但却功能强大的子文件 multiprocessing.dummy. .

Digression这是啥东西?没听说过线程引用叫dummy的多进程包文件。我也是直到最近才知道。它在多进程的说明文档中也只被提到了一句。它的效果也只是让大家直到有这么个东西而已。这可真是营销的失误!

Dummy是一个多进程包的完整拷贝。唯一不同的是,多进程包使用进程,而dummy使用线程(自然也有Python本身的一些限制)。所以一个有的另一个也有。这样在两种模式间切换就十分简单,并且在判断框架调用时使用的是IO还是CPU模式非常有帮助。

准备开始

准备使用带有并发的map功能首先要导入相关包文件:

from multiprocessing import Pool

from multiprocessing.dummy import Pool as ThreadPool

然后初始化:

pool = ThreadPool()

就这么简单一句解决了example2.py中build_worker_pool的功能. 具体来讲,它首先创建一些有效的worker启动它并将其保存在一些变量中以便随时访问。

pool对象需要一些参数,但现在最紧要的就是:进程。它可以限定线程池中worker的数量。如果不填,它将采用系统的内核数作为初值。

一般情况下,如果你进行的是计算密集型多进程任务,内核越多意味着速度越快(当然这是有前提的)。但如果是涉及到网络计算方面,影响的因素就千差万别。所以最好还是能给出合适的线程池大小数。

pool = ThreadPool(4) # Sets the pool size to 4

如果运行的线程很多,频繁的切换线程会十分影响工作效率。所以最好还是能通过调试找出任务调度的时间平衡点。

好的,既然已经建好了线程池对象还有那些简单的并发内容。咱们就来重写一些example2.py中的url opener吧!

看吧!只用4行代码就搞定了!其中三行还是固定写法。使用map方法简单的搞定了之前需要40行代码做的事!为了增加趣味性,我分别统计了不同线程池大小的运行时间。

结果:

效果惊人!看来调试一下确实很有用。当线程池大小超过9以后,在我本机上的运行效果已相差无几。

示例 2:

生成上千张图像的缩略图:

现在咱们看一年计算密集型的任务!我最常遇到的这类问题之一就是大量图像文件夹的处理。

其中一项任务就是创建缩略图。这也是并发中比较成熟的一项功能了。

基础单线程创建过程

作为示例来说稍微有点复杂。但其实就是传一个文件夹目录进来,获取到里面所有的图片,分别创建好缩略图然后保存到各自的目录当中。

在我的电脑上,处理大约6000张图片大约耗时27.9秒.

如果使用并发map处理替代其中的for循环:

只用了5.6 秒!

就改了几行代码速度却能得到如此巨大的提升。最终版本的处理速度还要更快。因为我们将计算密集型与IO密集型任务分派到各自独立的线程和进程当中,这也许会容易造成死锁,但相对于map强劲的功能,通过简单的调试我们最终总能设计出优美、高可靠性的程序。就现在而言,也别无它法。

好了。来感受一下一行代码的并发程序吧。

[转载] python并行处理任务_Python 并行任务技巧相关推荐

  1. python爬虫难点_Python爬虫技巧

    ​在本文中,我们将分析几个真实网站,来看看我们在<用Python写网络爬虫(第2版)>中学过的这些技巧是如何应用的.首先我们使用Google演示一个真实的搜索表单,然后是依赖JavaScr ...

  2. python keyboard方法_python 偷懒技巧——使用 keyboard 录制键盘事件

    之前在某本书上看到一个程序,可以通过 Python 记录下全局范围内的键盘事件,使用的是 ctypes 库. 后来几经尝试,始终不能成功运行.原来它只支持 Python2 和 32 位的 Window ...

  3. python keyboard方法_python 偷懒技巧――使用 keyboard 录制键盘事件

    之前在某本书上看到一个程序,可以通过 Python 记录下全局范围内的键盘事件,使用的是 ctypes 库. 后来几经尝试,始终不能成功运行.原来它只支持 Python2 和 32 位的 Window ...

  4. [转载] python set大小_python set集合

    参考链接: Python集合set Python set集合 最后更新于:2020-03-21 12:06:03 在python变量中除了以前文章所提到的整形int / 浮点数float / 布尔值b ...

  5. [转载] python仿真入门_python基础-入门

    参考链接: Pytho 集合set symmetric_difference() 主要包括: 1.变量 2.用户输入 3.if...else语句 4.for循环 5.while循环 6.break和c ...

  6. [转载] python 字典查找_python字典的增,删,改,查

    参考链接: Python字典clear() 字典---dict 1.字典是无序,可变的数据类型 2.字典:用于存储数据,存储大量数据,字典要比列表快,将数据和数据之间进行关联 定义一个字典: dic ...

  7. [转载] python hasattr函数_Python的hasattr() getattr() setattr() 函数使用方法详解

    参考链接: Python hasattr() hasattr(object, name) 判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回Fa ...

  8. [转载] python定义整型常量_Python笔记——数据类型、变量和常量

    参考链接: Python变量,常量和文字 数据类型 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频 ...

  9. [转载] python元组特点_python元组的优势有哪些

    参考链接: Python元组 在对于元组的学习上,想必大家都有了一定的使用心得.同时我们也进行过列表的使用,不过相较而言元组最大的特点就是不可改变的.那么这里我们就可以参照之前学习的列表,比较它们的一 ...

最新文章

  1. R假设检验之Breusch-Pagan检验(Breusch-Pagan Test)
  2. linux/usr/src/kernels 目录下没有内核源码 解决方法
  3. 1号店11.11:从应用架构落地点谈高可用高并发高性能--转载
  4. BeagleBone Black QNX6.6 BSP中IPL的完善
  5. linux基础命令篇一
  6. SpringSecurity remeber功能源码跟踪
  7. 使用基于 WebRTC 的 JavaScript API 在浏览器环境里调用本机摄像头
  8. 编写自己的Javascript库-1
  9. 排序算法——随机快速排序
  10. 操作系统死锁 四个必要条件
  11. STM32F429I-DISCO ucLinux 开发环境搭建
  12. 计算机用户名携带中文路径,Win10 User下的中文用户名改成英文路径操作方法
  13. 初识FineBI数据分析
  14. 经典算法之左边界二分查找法(俗称左边界二分搜索法)
  15. Python + ElasticSearch:有了这个超级武器,你也可以报名参加诗词大会了! | 博文精选...
  16. pes2017服务器维护时间,PES2017授权详情与球场数据包发布时间
  17. 哈工大软件构造 Git使用
  18. C#之控制台RPG类魔塔游戏
  19. R 计算数据框多个变量频次表
  20. 明解C语言(入门)——初识C语言

热门文章

  1. 【编辑器】VScode+code runner+python3编译
  2. 【HDOJ7059】Counting Stars(线段树,区间加,乘,标记)
  3. cheat给linux,[极客工具]cheat-linux命令行实用助记工具
  4. JavaScript流程分支结构(1)
  5. 计算机网络—计算机网络核心
  6. PETERSON互斥算法解析
  7. OpenGL基础24:聚光灯
  8. 后缀自动机线性构造方法
  9. 51nod-1246:罐子和硬币
  10. 手动绘制方向梯度直方图(HOG)