Python实际案例演示:一行Python代码实现并行

  

Python在程序并行化方面多少有些声名狼藉。撇开技术上的问题,例如线程的实现和吉尔,我觉得错误的教学指导才是主要问题。

  

常见的经典Python多线程,多进程教程多显得偏“重“。而且往往隔靴搔痒,没有深入探讨日常工作中最有用的内容。

  

  

  

简单搜索下“Python多线程教程“,不难发现几乎所有的教程都给出涉及类和队列的例子:

  <前>   <代码>导入操作系统   
进口公益诉讼   
  从多处理导入池
  从公益诉讼导入图片
  
  大小
=(75、75)   
SAVE_DIRECTORY=& # 39;拇指# 39;   
  
def get_image_paths(文件夹):   
,返回(os.path。加入(文件夹,f)   
,,,,,,在os.listdir f(文件夹)   
,,,,,,如果& # 39;jpeg # 39;在f)   
  
def create_thumbnail(文件名):   
,,im=Image.open(文件名)   
,即时通讯。缩略图(尺寸、Image.ANTIALIAS)   
,,基础、?os.path.split(文件名)   
,save_path=os.path。加入(基地,SAVE_DIRECTORY、帧)   
,,im.save (save_path)   
  
if __name__==& # 39; __main__ # 39;:   
,=os.path.abspath,文件夹(   
,,,,& # 39;_18_2013_r000_iqm_big_sur_mon__e10d1958e7b766c3e840& # 39; 11日)   
,os.mkdir (os.path。加入(文件夹,SAVE_DIRECTORY))   
  
,,图像=get_image_paths(文件夹)   
  
,池,池=()   
,池。地图(creat_thumbnail、图片)   
,,pool.close ()   
,代码,pool.join ()   

哈,看起来有些像Java不是吗?

  

我并不是说使用生产者/消费者模型处理多线程/多进程任务是错误的(事实上,这一模型自有其用武之地)。只是,处理日常脚本任务时我们可以使用更有效率的模型。

  

  

  

首先,你需要一个样板类,,   
其次,你需要一个队列来传递对象,,   
而且,你还需要在通道两端都构建相应的方法来协助其工作(如果需想要进行双向通信或是保存结果还需要再引入一个队列)。

  

  

  

按照这一思路,你现在需要一个工人线程的线程池。下面是一篇IBM经典教程中的例子,在进行网页检索时通过多线程进行加速。

  <前>   <代码> # Example2.py   
& # 39; & # 39; & # 39;   
一个更实际的线程池的例子   
& # 39; & # 39; & # 39;   
  
导入时间   
进口线程   
进口队列   进口urllib2
  
  
类消费者(threading.Thread):   
,队列,def __init__(自我):   
,,,,threading.Thread.__init__(自我)   
,,,自我。_queue=队列   
  
,,def运行(自我):   
,,,,而真正的:   
,,,,,,内容=self._queue.get ()   
,,,,,内容,如果isinstance (str)和内容==& # 39;退出# 39;:   
,,,,,,,,打破   
,,,,,,反应=urllib2.urlopen(内容)   
,,,,打印& # 39;再见是的! & # 39;   
  
def生产商():   
,,url=[   
,,,,& # 39;http://www.python.org& # 39; & # 39; http://www.yahoo.com& # 39;   
,,,,& # 39;http://www.scala.org& # 39; & # 39; http://www.google.com& # 39;   
,,,,#等。   
,,)   
,,队列=Queue.Queue ()   
,,worker_threads=build_worker_pool(队列,4)   
,,start_time=time.time ()   
  
,# url添加到流程   
,的网址,网址:   
,,,,queue.put (url),   
,#添加毒pillv   
,,工人在worker_threads:   
,,,,queue.put(& # 39;退出# 39;)   
,,工人在worker_threads:   
,,,,worker.join ()   
  
,,打印& # 39;完成了!时间:{}& # 39;.format (time.time () - start_time)   
  
def build_worker_pool(队列、大小):   
,,工人=[]   
,,_的范围(大小):   
,,,,工人=消费者(队列)   
,,,,worker.start ()   
,,,,workers.append(工人)   
,工人,返回   
  
if __name__==& # 39; __main__ # 39;:   
,,生产者()   

这段代码能正确的运行,但仔细看看我们需要做些什么:构造不同的方法,追踪一系列的线程,还有为了解决恼人的死锁问题,我们需要进行一系列的加入操作。这还只是开始……

  

至此我们回顾了经典的多线程教程,多少有些空洞不是吗?样板化而且易出的错,这样事倍功半的风格显然不那么适合日常使用,好在我们还有更好的方法。

  

  

  

地图这一小巧精致的函数是简捷实现Python程序并行化的关键. map源于Lisp这类函数式编程语言。它可以通过一个序列实现两个函数之间的映射。

Python实际案例演示:一行Python代码实现并行