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()

  

concurrent.futures进行并发编程的更多相关文章

  1. 使用concurrent.futures模块并发,实现进程池、线程池

    Python标准库为我们提供了threading和multiprocessing模块编写相应的异步多线程/多进程代码 从Python3.2开始,标准库为我们提供了concurrent.futures模 ...

  2. disruptor - Concurrent Programming Framework 并发编程框架

    disruptor发布了Java的2.0版本(.Net版本见这里),disruptor是一个高性能的异步处理框架,或者可以认为是最快的消息框架(轻量的JMS),也可以认为是一个观察者模式实现,或者事件 ...

  3. python系列之 - 并发编程(进程池,线程池,协程)

    需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...

  4. python并发编程之进程池,线程池,协程

    需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...

  5. concurrent.futures模块(进程池/线程池)

    需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...

  6. Python之网络编程之concurrent.futures模块

    需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...

  7. python并发编程之进程池、线程池、协程

    需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...

  8. python并发编程之进程池,线程池concurrent.futures

    进程池与线程池 在刚开始学多进程或多线程时,我们迫不及待地基于多进程或多线程实现并发的套接字通信,然而这种实现方式的致命缺陷是:服务的开启的进程数或线程数都会随着并发的客户端数目地增多而增多, 这会对 ...

  9. 《转载》Python并发编程之线程池/进程池--concurrent.futures模块

    本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...

随机推荐

  1. js 检查登录态方法封装(闭包、状态缓存)

    前端页面开发时,经常需要异步校验登录态,每次都重新copy之前写的方法,比较繁琐不好维护,固将登录态校验封装成一个js. (function(){ //登录状态 1 登录态有效 2 登录态无效 3 请 ...

  2. MGR

    单主模式 参数修改 server_id=1 gtid_mode=ON enforce_gtid_consistency=ON binlog_checksum=NONE log_bin=binlog l ...

  3. Cookie/Session的机制与安全

    转载自:https://harttle.land/2015/08/10/cookie-session.html Cookie和Session是为了在无状态的HTTP协议之上维护会话状态,使得服务器可以 ...

  4. Asp.net MVC WebApi项目的自动接口文档及测试功能打开方法

    https://blog.csdn.net/foren_whb/article/details/78866133

  5. Linux进程PRI与NI值

    1.PRI -> 进程的优先级,大部分系统(Linux.UCOSII)都是数字越低优先级越高,进程就优先运行 , Linux中的PRI(new) = PRI(old) + nice ,其中 , ...

  6. Apache的功能模块

    本人这几天一直在看apache相关的书籍,稍微说下apache的结构 本人的制图: Apache一共有五层功能结构. 从底层到上依次为: 第一层: 名称:操作系统支持层 功能:操作系统可以提供底层功能 ...

  7. js中的this指向问题(小计)

    this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定,this最终指向调用它的对象. 1.函数调用模式 当一个函数并非一个对象的属性时,那么它就是被当做函数来调用的.在此种模式下,t ...

  8. #WEB安全基础 : HTTP协议 | 0x10 请求和响应报文重点结构及常见头部

    你需要认识一些常见的头部以及了解报文的详细结构 请求报文的请求行 GET/HTTP/1.1 响应报文的响应行 HTTP/1.1 200 OK 想必这些大家都知道了 请求 我访问一个页面 Host // ...

  9. svn 安装

    SVN简介: 为什么要使用SVN? 程序员在编写程序的过程中,每个程序员都会生成很多不同的版本,这就需要程序员有效的管理代码,在需要的时候可以迅速,准确取出相应的版本. Subversion是什么? ...

  10. python小程序--one

    #!/usr/bin/env python # _*_ coding:utf8 _*_ import sys user_lock_file="user_lock.txt" # 用户 ...