python 并发 ThreadPoolExecutor
正文:
Executor是一个抽象类,子类:
ThreadPoolExecutor和ProcessPoolExecutor ,一个线程池,一个进程池.
future对象:在未来的某一时刻完成操作的对象.
submit方法可以返回一个future对象,此对象直接返回,等线程函数执行完后把return的数据再set_result到future对象中;
下面实现了submit, map 与 as_completed的差别 , 下面的例子中都没有使用with ,实际使用时需要调用shutdown , 或用with
#线程执行的函数
def add(n1,n2):
v = n1 + n2
print('add :', v , ', tid:',threading.currentThread().ident)
time.sleep(n1)
return v
#通过submit把需要执行的函数扔进线程池中.
#submit 直接返回一个future对象
ex = ThreadPoolExecutor(max_workers=3) #制定最多运行N个线程
f1 = ex.submit(add,2,3)
f2 = ex.submit(add,2,2)
print('main thread running')
print(f1.done()) #done 看看任务结束了没
print(f1.result()) #获取结果 ,阻塞方法
注意 map 方法,返回是跟你提交序列是一致的. 是有序的
#下面是map 方法的简单使用. 注意:map 返回是一个生成器 ,并且是*有序的*
URLS = ['http://www.baidu.com', 'http://www.qq.com', 'http://www.sina.com.cn']
def get_html(url):
print('thread id:',threading.currentThread().ident,' 访问了:',url)
return requests.get(url) #这里使用了requests 模块
ex = ThreadPoolExecutor(max_workers=3)
res_iter = ex.map(get_html,URLS) #内部迭代中, 每个url 开启一个线程
for res in res_iter: #此时将阻塞 , 直到线程完成或异常
print('url:%s ,len: %d'%(res.url,len(res.text)))
接下来,使用as_completed . 这个函数为submit 而生, 为啥呢?
你总想通过一种办法来解决submit后啥时候完成的吧 , 而不是一次次调用future.done 或者 使用 future.result 吧.
concurrent.futures.as_completed(fs, timeout=None) 返回一个生成器,在迭代过程中会阻塞,
直到线程完成或者异常时,返回一个被set_result的Future对象.
同时注意, map方法返回是有序的, as_completed 是那个线程先完成/失败 就返回
#这是一个简单的 as_completed
URLS = ['http://www.baidu.com', 'http://www.qq.com', 'http://www.sina.com.cn']
def get_html(url):
time.sleep(3)
print('thread id:',threading.currentThread().ident,' 访问了:',url)
return requests.get(url) #这里使用了requests 模块
ex = ThreadPoolExecutor(max_workers=3)
f = ex.submit(get_html,URLS[0]) #提交一个任务,放入线程池中,准备执行
print('main thread running')
for future in as_completed([f]): #as_completed()接受一个可迭代的Future序列,返回一个生成器,在完成或异常时返回这个Future对象
print('一个任务完成.')
print(future.result())
#as_completed 完整的例子
#as_completed 返回一个生成器,用于迭代, 一旦一个线程完成(或失败) 就返回
URLS = ['http://www.baidu.com', 'http://www.qq.com', 'http://www.sina.com.cn']
def get_html(url):
time.sleep(1)
print('thread id:',threading.currentThread().ident,' 访问了:',url)
return requests.get(url) #这里使用了requests 模块
ex = ThreadPoolExecutor(max_workers=3) #最多3个线程
future_tasks = [ex.submit(get_html,url) for url in URLS] #创建3个future对象
for future in as_completed(future_tasks): #迭代生成器
try:
resp = future.result()
except Exception as e:
print('%s'%e)
else:
print('%s has %d bytes!'%(resp.url, len(resp.text)))
"""
thread id: 5160 访问了: http://www.baidu.com
thread id: 7752 访问了: http://www.sina.com.cn
thread id: 5928 访问了: http://www.qq.com
http://www.qq.com/ has 240668 bytes!
http://www.baidu.com/ has 2381 bytes!
https://www.sina.com.cn/ has 577244 bytes!
"""
wait 是阻塞函数,第一个参数和as_completed一样, 一个可迭代的future序列,返回一个元组 ,包含2个set , 一个完成的,一个未完成的
"""
wait 例子
参数:
FIRST_COMPLETED 当任何未来完成或被取消时,该函数将返回。 FIRST_EXCEPTION 当任何未来通过提出异常完成时,函数将返回。如果没有未来引发异常,那么它等同于 ALL_COMPLETED。 ALL_COMPLETED(默认) 当所有future完成或被取消时,函数将返回。
"""
URLS = ['http://www.baidu.com', 'http://www.qq.com', 'http://www.sina.com.cn']
def get_html(url):
time.sleep(1)
print('thread id:',threading.currentThread().ident,' 访问了:',url)
return requests.get(url) #这里使用了requests 模块
ex = ThreadPoolExecutor(max_workers=3) #最多3个线程
future_tasks = [ex.submit(get_html,url) for url in URLS] #创建3个future对象
try:
result = wait(future_tasks,return_when = fu.FIRST_COMPLETED)
done_set = result[0]
for future in done_set:
resp = future.result()
print('第一个网页任务完成 url:%s , len:%d bytes! ' % (resp.url, len(resp.text)))
except Exception as e:
print('exception :' , e)
最后说一下回调:add_done_callback(fn) , 回调函数是在调用线程完成后再调用的,在同一个线程中.
import os,sys,time,requests,threading
from concurrent import futures URLS = [
'http://baidu.com',
'http://www.qq.com',
'http://www.sina.com.cn'
] def load_url(url):
print('tid:',threading.currentThread().ident,',url:',url)
with requests.get(url) as resp:
return resp.content
def call_back(obj):
print('->>>>>>>>>call_back , tid:',threading.currentThread().ident, ',obj:',obj) with futures.ThreadPoolExecutor(max_workers=3) as ex:
# mp = {ex.submit(load_url,url) : url for url in URLS}
mp = dict()
for url in URLS:
f = ex.submit(load_url,url)
mp[f] = url
f.add_done_callback(call_back)
for f in futures.as_completed(mp):
url = mp[f]
try:
data = f.result()
except Exception as exc:
print(exc, ',url:',url)
else:
print('url:', url, ',len:',len(data),',data[:20]:',data[:20])
"""
tid: 7128 ,url: http://baidu.com
tid: 7892 ,url: http://www.qq.com
tid: 3712 ,url: http://www.sina.com.cn
->>>>>>>>>call_back , tid: 7892 ,obj: <Future at 0x2dd64b0 state=finished returned bytes>
url: http://www.qq.com ,len: 251215 ,data[:20]: b'<!DOCTYPE html>\n<htm'
->>>>>>>>>call_back , tid: 3712 ,obj: <Future at 0x2de07b0 state=finished returned bytes>
url: http://www.sina.com.cn ,len: 577333 ,data[:20]: b'<!DOCTYPE html>\n<!--'
->>>>>>>>>call_back , tid: 7128 ,obj: <Future at 0x2d533d0 state=finished returned bytes>
url: http://baidu.com ,len: 81 ,data[:20]: b'<html>\n<meta http-eq'
"""
python 并发 ThreadPoolExecutor的更多相关文章
- Python并发复习1 - 多线程
一.基本概念 程序: 指令集,静态, 进程: 当程序运行时,会创建进程,是操作系统资源分配的基本单位 线程: 进程的基本执行单元,每个进程至少包含一个线程,是任务调度和执行的基本单位 > 进程和 ...
- Python并发编程二(多线程、协程、IO模型)
1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...
- Python并发编程一(多进程)
1.背景知识(进程.多道技术) 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一 ...
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...
- Python并发编程系列之多线程
1 引言 上一篇博文详细总结了Python进程的用法,这一篇博文来所以说Python中线程的用法.实际上,程序的运行都是以线程为基本单位的,每一个进程中都至少有一个线程(主线程),线程又可以创建子线程 ...
- python并发模块之concurrent.futures(二)
python并发模块之concurrent.futures(二) 上次我们简单的了解下,模块的一些基本方法和用法,这里我们进一步对concurrent.futures做一个了解和拓展.上次的内容点这. ...
- python并发编程&多线程(二)
前导理论知识见:python并发编程&多线程(一) 一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性 官网链 ...
- python并发编程&多进程(一)
本篇理论居多,实际操作见: python并发编程&多进程(二) 一 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行) ...
- 快速了解Python并发编程的工程实现(上)
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...
随机推荐
- 一个简单的CSS登录页
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 给博客使用Butterfly主题并部署到GitHub服务器
目录 前言 一.安装Butterfly主题 二.将本地博客部署到GitHub服务器 三.将个人域名与GitHub绑定 前言 安装完Hexo框架后,自带的主题在thems文件夹下可以查看,应用后界面: ...
- Quartz.Net系列(三):解读Quartz.Net源码领略设计模式在其中的应用
1.Builder(建造者)模式 JobBuilder DateBuilder 其他的Builder(TriggerBuilder.SchedulerBuilder等) 2.抽象工厂模式 ISch ...
- 从零开始的Spring Boot(4、Spring Boot整合JSP和Freemarker)
Spring Boot整合JSP和Freemarker 写在前面 从零开始的Spring Boot(3.Spring Boot静态资源和文件上传) https://www.cnblogs.com/ga ...
- [实战] Flutter 上的内存泄漏监控
一.前言 Flutter 所使用的 Dart 语言具有垃圾回收机制,有垃圾回收就避免不了会内存泄漏. 在 Android 平台上有个内存泄漏检测工具 LeakCanary, 它可以方便地在 debug ...
- opencv Scalar
template<typename _Tp> class Scalar_ : public Vec<_Tp, 4> { public: //! various construc ...
- 深拷贝和浅拷贝以及void里的return用法
Object o1=new Object(); Object o2; int i1=3,i2; 浅拷贝 o2=o1;i2=i1; 深拷贝 o2=new Object();o2=o1.clone(); ...
- springMvc接口开发--对访问的restful api接口进行拦截实现功能扩展
1.视频参加Spring Security开发安全的REST服务\PART1\PART1 3-7 使用切片拦截REST服务三通it学院-www.santongit.com-.mp4 讲的比较的经典,后 ...
- 一场由yield引发的连串拷问
最近在学习Python中生成器时,遇到了一个yield关键词,廖雪峰老师的官网中也没有详细的解释,经过一番查阅和研究,终于对它有了一些认识并做了总结(如有不对之处,还请大神指正). 首先先简单了解下生 ...
- 2020_06_18Mysql事务
1.事务的基本介绍 1.概念:一个包含多个步骤的事务,被事务管理,要么同时成功,要么同时失败. 2.操作: 2.1 开启事务:start transaction; 2.2 回滚:rollback; 2 ...