Python并发concurrent.futures和asyncio的用法

  介绍

这篇文章主要讲解了Python并发concurrent.futures和asyncio的用法,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。

<强>说明

Python标准库为我们提供了线程和多处理模块编写相应的多线程/多进程代码。

从Python3.2开始,标准库为我们提供了concurrent.futures模块,并发。期货模块的主要特色是ThreadPoolExecutor和

ProcessPoolExecutor类,这两个类实现的接口能分别在不同的线程或进程中执行可调

用的对象。这两个类在内部维护着一个工作线程或进程池,以及要执行的任务队列。

Python 3.4以后标准库中asyncio包,这个包使用事件循环驱动的协程实现并发。这是Python中最大也

是最具雄心壮志的库之一.asyncio大量使用收益率从表达式,因此与

Python旧版不兼容。

<强>提交和地图方法

提交方法作用是向线程池提交可回调的任务,并返回一个回调实例。

例子:

进口时间
  从并发。期货进口ThreadPoolExecutor
  
  #可回调的任务
  def pub_task(味精):
  time . sleep (3)
  返回味精
  
  #创建一个线程池
  池=ThreadPoolExecutor (max_workers=3)
  
  #往线程池加入2个任务
  task1=池。提交(pub_task & # 39;一个# 39;)
  task2=池。提交(pub_task & # 39; b # 39;)
  
  print (task1.done()) #假
  time . sleep (4)
  print (task2.done()) #真正的
  
  print (task1.result ())
  print (task2.result ()) 

地图方法是创建一个迭代器,回调的结果有序放在迭代器中。

<强>问题:

执行人。地图函数易于使用,不过有个特性可能有用,也可能没的用,具体情况取决于需求:这个函数返回结果的顺序与调用开始的顺序一致。

如果第一个调用生成结果用10秒时,而其他调用只用1秒,代码会阻塞10秒,获取地图方法返回的生成器产出的第一个结果。

在此之后,获取后续结果时不会阻塞,因为后续的调用已经结束。

如果必须等到获取所有结果后再处理,这种行为没问题,不过,通常更可取的方式是,不管提交的顺序,只要有结果就获取。

为此,要把遗嘱执行人。提交方法和期货。as_completed函数结合起来使用。

。期货进口ThreadPoolExecutor
  进口的要求
  
  url=[& # 39; http://www.csdn.com& # 39; & # 39; http://qq.com& # 39;, & # 39; http://www.leasonlove.cn& # 39;】
  
  def任务(url,超时=10):
  返回请求。get (url,超时=超时)
  
  池=ThreadPoolExecutor (max_workers=3)
  结果=池。地图(任务、url)
  
  受潮湿腐烂的结果:
  打印(& # 39;% s % & # 39;% (ret.url (ret) 

<强>未来异步编程

未来可以理解为一个在未来完成的操作,这是异步编程的基础。通常情况下,我们执行io操作,访问url时(如下)在等待结果返回之前会产生阻塞,cpu不能做其他事情,而未来的引入帮助我们在等待的这段时间可以完成其他的操作。

。期货进口ThreadPoolExecutor
  从并发。期货进口as_completed
  进口的要求
  
  url=[& # 39; http://www.csdn.cn& # 39; & # 39; http://qq.com& # 39;, & # 39; http://www.leasonlove.cn& # 39;】
  
  def任务(url,超时=1):
  返回请求。get (url,超时=超时)
  
  ThreadPoolExecutor (max_workers=3)作为遗嘱执行人:
  future_tasks=[执行人。提交(任务,url)的url网址)
  
  在future_tasks f:
  如果f.running ():
  打印(& # 39;% s运行# 39;% str (f))
  
  在as_completed f (future_tasks):
  试一试:
  ret=f.done ()
  如果延迟:
  f_ret=f.result ()
  打印(& # 39;% s,完成,结果:% s, % & # 39;% (str (f), f_ret。url, f_ret.content))
  除了例外e:
  第号一个url无响应
  f.cancel ()
  打印(str (e)) 

<强> asyncio库协程实现并发

对于gevent和asyncio建议大家放弃gevent,拥抱asyncio, asyncio是Python3.4以后标准库。

而且由于gevent直接修改标准库里面大部分的阻塞式系统调用,包括插座、ssl、线程和选择等模块,而变为协作式运行。

但是我们无法保证你在复杂的生产环境中有哪些地方使用这些标准库会由于打了补丁而出现奇怪的问题。

进口asyncio
  导入的时间
  开始=time.time ()
  
  异步def (x):
  打印(& # 39;等待:& # 39;,x)
  等待asyncio.sleep (x)
  后返回& # 39;完成{}& # 39;.format (x)
  
  task1=(1)
  task2=(2)
  task3=(4)
  
  任务=[
  asyncio.ensure_future (task1),
  asyncio.ensure_future (task2),
  asyncio.ensure_future (task3)
  ]
  
  循环=asyncio.get_event_loop ()
  loop.run_until_complete (asyncio.wait(任务)
  
  任务的任务:
  打印(& # 39;任务结果:& # 39;,task.result ())
  
  结束=time.time ()
  打印(& # 39;时间:& # 39;,结束-开始)

Python并发concurrent.futures和asyncio的用法