Python中进行并发编程一般使用threading和multiprocessing模块,不过大部分的并发编程任务都是派生一系列线程,从队列中收集资源,然后用队列收集结果。在这些任务中,往往需要生成线程池,concurrent.futures模块对threading和multiprocessing模块进行了进一步的包装,可以很方便地实现池的功能。

下载

python3中concurrent.futures是标准库,在python2中还需要自己安装futures:

pip install futures

Executor与Future

concurrent.futures供了ThreadPoolExecutor和ProcessPoolExecutor两个类,都继承自Executor,分别被用来创建线程池和进程池,接受max_workers参数,代表创建的线程数或者进程数。ProcessPoolExecutor的max_workers参数可以为空,程序会自动创建基于电脑cpu数目的进程数。

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import requests def load_url(url):
return requests.get(url) url = 'http://httpbin.org'
executor = ThreadPoolExecutor(max_workers=1)
future = executor.submit(load_url, url)

Executor中定义了submit()方法,这个方法的作用是提交一个可执行的回调task,并返回一个future实例。future能够使用done()方法判断该任务是否结束,done()方法是不阻塞的,使用result()方法可以获取任务的返回值,这个方法是阻塞的。

print future.done()
print future.result().status_code

Future类似于js中的Promise,可以添加回调函数:

future.add_done_callback(fn)

回调函数fn在future取消或者完成后运行,参数是future本身。

submit()方法只能进行单个任务,用并发多个任务,需要使用map与as_completed。

map

URLS = ['http://httpbin.org', 'http://example.com/', 'https://api.github.com/']

def load_url(url):
return requests.get(url) with ThreadPoolExecutor(max_workers=3) as executor:
for url, data in zip(URLS, executor.map(load_url, URLS)):
print('%r page status_code %s' % (url, data.status_code))

 结果:

'http://httpbin.org' page status_code 200
'http://example.com/' page status_code 200
'https://api.github.com/' page status_code 200

 map方法接收两个参数,第一个为要执行的函数,第二个为一个序列,会对序列中的每个元素都执行这个函数,返回值为执行结果组成的生成器。

由上面可以看出返回结果与序列结果的顺序是一致的

as_completed

as_completed()方法返回一个Future组成的生成器,在没有任务完成的时候,会阻塞,在有某个任务完成的时候,会yield这个任务,直到所有的任务结束。

def load_url(url):
return url, requests.get(url).status_code with ThreadPoolExecutor(max_workers=3) as executor:
tasks = [executor.submit(load_url, url) for url in URLS]
for future in as_completed(tasks):
print future.result()

结果:

('http://example.com/', 200)
('http://httpbin.org', 200)
('https://api.github.com/', 200)

可以看出,结果与序列顺序不一致,先完成的任务会先通知主线程。

wait

wait方法可以让主线程阻塞,直到满足设定的要求。有三种条件ALL_COMPLETED, FIRST_COMPLETED,FIRST_EXCEPTION。

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, wait, ALL_COMPLETED, FIRST_COMPLETED
from concurrent.futures import as_completed
import requests URLS = ['http://httpbin.org', 'http://example.com/', 'https://api.github.com/'] def load_url(url):
requests.get(url)
print url with ThreadPoolExecutor(max_workers=3) as executor:
tasks = [executor.submit(load_url, url) for url in URLS]
wait(tasks, return_when=ALL_COMPLETED)
print 'all_cone'

 返回:

http://example.com/
http://httpbin.org
https://api.github.com/
all_cone

 可以看出阻塞到任务全部完成。

ProcessPoolExecutor

使用ProcessPoolExecutor与ThreadPoolExecutor方法基本一致,注意文档中有一句:

The __main__ module must be importable by worker subprocesses. This means that ProcessPoolExecutor will not work in the interactive interpreter.

需要__main__模块。

def main():
with ProcessPoolExecutor() as executor:
tasks = [executor.submit(load_url, url) for url in URLS]
for f in as_completed(tasks):
ret = f.done()
if ret:
print f.result().status_code if __name__ == '__main__':
main()

  

最新文章

  1. 简单的Linux的用户权限管理
  2. BZOJ3461 : Jry的时间表
  3. [noi2011]道路修建 树形dp
  4. ionic中登陆逻辑控制
  5. CSS padding margin border属性详解【转载】
  6. C#调用R语言输出图片
  7. hql中or的用法(代替union)
  8. cf734 E. Anton and Tree
  9. 23_迭代器、模拟For循环
  10. 简单介绍shell编程四剑客之grep
  11. Apache Maven 3.6.1配置安装
  12. 【css】3d导航效果
  13. fiddler学习笔记2 字段说明;移动设备、解密证书
  14. Vue: 用 key 管理可复用的元素
  15. CC攻击与DDOS攻击区别
  16. 【JAVA】抽象类,抽象方法
  17. FFmpeg(9)-解码器解码代码演示(FFmpeg调用MediaCodec实现硬解码、多线程解码、及音视频解码性能测试)
  18. 牛客Wannafly挑战赛11E 白兔的刁难
  19. STM32启动代码分析
  20. 几个并发的术语解释——QPS,TPS,PV

热门文章

  1. DDoS攻击流量检测方法
  2. mysql 日期 字符串
  3. 一、初识CocoaPods——XCode的依赖库管理工具
  4. cnblog项目--20190309
  5. aos.css 动画效果
  6. qt 画多边形(实现鼠标拖动节点)
  7. Back up and restore information in Firefox profiles
  8. 虚拟机设置固定ip可以使shell远程连接到服务器
  9. Promise的那些事儿
  10. Visual Studio 项目依赖