python 协程池gevent.pool_进程池\线程池,协程,gevent
目录
1. 进程池与线程池
2. 协程
3. gevent
4. 单线程下实现并发的套接字通信
首先写一个基于多线程的套接字
服务端:
from socket import *
from threading import Thread
def comunicate(conn):
while True: # 通信循环
try:
data = conn.recv(1024)
if len(data) == 0: break
conn.send(data.upper())
except ConnectionResetError:
break
conn.close()
def server(ip, port, backlog=5):
server = socket(AF_INET, SOCK_STREAM)
server.bind((ip, port))
server.listen(backlog)
while True: # 链接循环
conn, client_addr = server.accept()
print(client_addr)
# 通信
t=Thread(target=comunicate,args=(conn,))
t.start()
if __name__ == '__main__':
s=Thread(target=server,args=('127.0.0.1',8081))
s.start()
每连接上一个客户端便会创造一个线程 , 那么如果有一万个客户端的话服务端会产生一万个线程 , 然后服务端就炸了 , 所以要想个办法限制连接个数 , 即限制
1. 进程池\线程池
开启一个进程池 , 会开启一定个数的进程 , 然后将任务提交给进程就可以了
1 介绍
concurrent.futures模块提供了高度封装的异步调用接口
ThreadPoolExecutor:线程池,提供异步调用
ProcessPoolExecutor: 进程池,提供异步调用
Both implement the same interface, which is defined by the abstract Executor class.
2 基本方法
submit(fn, *args, **kwargs)
异步提交任务
map(func, *iterables, timeout=None, chunksize=1)
取代for循环submit的操作
shutdown(wait=True)
相当于进程池的pool.close()+pool.join()操作
wait=True,等待池内所有任务执行完毕回收完资源后才继续
wait=False,立即返回,并不会等待池内的任务执行完毕
但不管wait参数为何值,整个程序都会等到所有任务执行完毕
submit和map必须在shutdown之前
result(timeout=None)
取得结果
add_done_callback(fn)
回调函数
导入模块
from concurrent.futures import ProcessPoolExecutor
创建一个进程池
p=ProcessPoolExecutor(4)#进程数为4
提交任务, 有两种方式
a.同步调用:同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行的
res=p.submit(function,参数一...).result()
b. 异步调用:提交完一个任务之后,不在原地等待,而是直接执行下一行代码,会导致任务是并发执行的,,结果futrue对象会在任务运行完毕后自动传给回调函数
res=p.submit(function,参数一...)
回调函数(用于异步调用)
每提交一个任务 , 会产生一个对象 , 给这个任务绑定了一个函数 , 这个函数会在你提交的任务完成后自动触发 , 且会将这个对象当作参数传给这个函数
这个函数用于处理子进程运行完之后产生的结果
多进程下的回调函数
from concurrent.futures import ProcessPoolExecutor
import time,os
import requests
def get(url):
print('%s GET %s' %(os.getpid(),url))
time.sleep(3)#处理的太快看不出效果 , 模拟多处理3秒
response=requests.get(url)#爬取网站内容
if response.status_code == 200:
res=response.text
else:
res='下载失败'
return res#返回爬取数据
# 到这里任务运行完了之后自动调用parse函数 ,
# 回调函数 , 处理任务的结果用
def parse(future):
time.sleep(1)
res=future.result()#future对象下的result为任务的返回值
print('%s 解析结果为%s' %(os.getpid(),len(res)))
if __name__ == '__main__':
urls=[
'https://www.baidu.com',
'https://www.sina.com.cn',
'https://www.tmall.com',
'https://www.jd.com',
'https://www.python.org',
'https://www.openstack.org',
'https://www.baidu.com',
'https://www.baidu.com',
'https://www.baidu.com',
]
#开启进程数为9的进程池
p=ProcessPoolExecutor(9)
start=time.time()
for url in urls:
# 异步调用:提交完一个任务之后,不在原地等待,而是直接执行下一行代码,会导致任务是并发执行的,,结果futrue对象会在任务运行完毕后自动传给回调函数
future=p.submit(get,url)
#将parse设为回调函数
future.add_done_callback(parse) #parse会在任务运行完毕后自动触发,然后接收一个参数future对象
p.shutdown(wait=True)
print('主',time.time()-start)
print('主',os.getpid())
多线程与多进程相同,只需将p=ProcessPoolExecutor(9)改为p=ThreadPoolExecutor(9)就可以了
2. 单线程下实现并发-------协程
目标:
在单线程下实现并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。
并发(多个任务看起来是同时执行就是并发):切换+保存状态
协程:
协程是单线程实现并发
注意:协程是程序员意淫出来的东西,操作系统里只有进程和线程的概念(操作系统调度的是线程)
在单线程下实现多个任务间遇到IO就切换就可以降低单线程的IO时间,从而最大限度地提升单线程的效率
强调
python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关)
对比操作系统控制线程的切换,用户在单线程内控制协程的切换
优点如下
协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
单线程内就可以实现并发的效果,最大限度地利用cpu
缺点如下
协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
总结
必须在只有一个单线程里实现并发
修改共享数据不需加锁
用户程序里自己保存多个控制流的上下文栈
附加:一个协程遇到IO操作自动切换到其它协程(如何实现检测IO,yield、greenlet都无法实现,就用到了gevent模块(select机制))
3. gevent
他是一个第三方的库 , 可以实现在单线程内遇到 IO 任务自动切换
geven是不能直接识别的 需要在整个文件最前面加上一行代码
from gevent import monkey;monkey.patch_all()
步骤 :
打补丁
导入from gevent import spawn
定义有 IO 操作的任务(函数)
将多个任务分别提交给协程
g1=spawn(函数名,函数的参数)
g2=spawn(函数名,函数的参数)
等待两个协程运行完 ,
g1.join()
g2.join()
:因为这里是异步调用 , 主线程代码运行完了 , 主线程就会死掉 , 协程里面的任务也不会运行完 就跟着死了, 所以要加上join方法 ,如果主线程要运行很久 , 或者是一个死循环 , 就不用加join方法 ,即上面的的第五步就可以忽略
from gevent import monkey;monkey.patch_all()
from gevent import spawn,joinall #pip3 install gevent
import time
def play(name):
print('%s play 1' %name)
time.sleep(5)
print('%s play 2' %name)
def eat(name):
print('%s eat 1' %name)
time.sleep(3)
print('%s eat 2' %name)
start=time.time()
g1=spawn(play,'王昭锦')
g2=spawn(eat,'王昭锦')
g1.join()
g2.join()
# joinall([g1,g2]) #上面两步可以并成这一步
print('主',time.time()-start)
运行结果如下:
'''
王昭锦 play 1
王昭锦 eat 1
王昭锦 eat 2
王昭锦 play 2
主 5.009259223937988
'''
4. 单线程下实现并发的套接字通信
服务端:
from gevent import monkey;monkey.patch_all()
from socket import *
from gevent import spawn
def comunicate(conn):
while True: # 通信循环
try:
data = conn.recv(1024)
if len(data) == 0: break
conn.send(data.upper())
except ConnectionResetError:
break
conn.close()
def server(ip, port, backlog=5):
server = socket(AF_INET, SOCK_STREAM)
server.bind((ip, port))
server.listen(backlog)
while True: # 链接循环
conn, client_addr = server.accept()
print(client_addr)
# 通信
spawn(comunicate,conn)
if __name__ == '__main__':
g1=spawn(server,'127.0.0.1',8080)
g1.join()
python 协程池gevent.pool_进程池\线程池,协程,gevent相关推荐
- Python进阶(5)_进程与线程之协程、I/O模型
三.协程 3.1协程概念 协程:又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存 ...
- 进程 线程 协程_进程,线程,协程那些事
无论我们写出怎样的程序,最后都是由操作系统来运行我们的程序,而操作系统如何管理我们的程序,我们程序的数据如何保存和计算,这些都是操作系统需要处理的事情,我们只要将写好的程序交给操作系统就好. 虽然操作 ...
- 进程、线程、协程和管程的区别
大家都知道,计算机是为了模拟现实世界,其中计算机领域最伟大的发明之一就是操作系统.操作系统对于计算机来说是其核心的存在,可以说操作系统的地位就像计算机的灵魂一样.操作系统的诞生是为了运行用户程序,事实 ...
- python是如何实现进程池和线程池的_进程、线程、线程池和协程如何理解?
1.进程.线程.线程池的概念 进程是一个动态的过程,是一个活动的实体.简单来说,一个应用程序的运行就可以被看做是一个进程,而线程,是运行中的实际的任务执行者.可以说,进程中包含了多个可以同时运行的线程 ...
- 怎么更进一步学python_【百尺竿头,更进一步学Python】Python进阶课程——进程,线程和协程的区别...
本文带来各类奇怪的IT百科知识. [百尺竿头,更进一步学Python]Python进阶课程--进程:线程和协程的区别 现在多进程多线程已经是老生常谈了:协程也在最近几年流行起来.今天我们本文主要介绍进 ...
- python 协程、进程、线程_Python 中的进程、线程、协程
1. 进程 进程是正在运行的程序实例,是内核分配资源的最基本的单元.进程拥有自己独立的堆和栈,独立的地址空间,资源句柄.进程由 OS 调度,调度开销较大,在并发的切换过程效率较低. Python 提供 ...
- python提高——进程、线程、协程对比及代码实现
目录 1多任务 1.1并发 1.2并行 2线程 2.1引入线程 2.2线程进行顺序 2.3线程封装 2.4多线程-共享全局变量 2.5资源竞争 2.6互斥锁 2.7死锁 3进程 3.1进程创建 3.2 ...
- python进程线程协程区别_进程和线程、协程的区别
现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中有协程库gevent,py web框架tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区 ...
- python线程协程进程的区别_进程和线程、协程的区别
现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中有协程库gevent,py web框架tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区 ...
- Python 进程、线程、协程
进程.线程.协程 一.线程 1. 进程和线程 线程:计算机中可以被cpu调度的最小单元(真正在工作). 进程:计算机资源分配的最小单元(进程为线程提供资源). #如容器,资源隔离使用的进程级别隔离.一 ...
最新文章
- 吸水间最低动水位标高_水库水位库容监测系统方案
- 命名实体识别学习笔记——使用Ltp
- IDEA 新特性:提前知道代码怎么走
- NR 5G UE初始接入流程
- 成功解决ValueError: row index was 65536, not allowed by .xls format
- BERT源码分析(PART II)
- android 随机布尔值,在 Android 的某些机型,v1.2.2 v1.2.1 加密会导致 boolean 类型的值丢失的问题...
- html5离线储存不足,html5的离线存储问题
- C++学习之路 | PTA(甲级)—— 1099 Build A Binary Search Tree (30分)(带注释)(精简)
- 深入学习webpack(四)
- 电脑cpu和手机cpu的差距有多大?
- Selenium2Library(RF)浏览器打不开问题汇总
- Android 开发环境搭建之——ADT-Bundle for Windows
- 洪恩在线c语言测试,洪恩软件之编程之道C/C++程序设计入门视频教程
- 计算机桌面word不见怎么办,电脑桌面word 电脑桌面上word不见了怎么办
- IOS应用在iPhone5和iPhone5s上不能全屏显示,应用画面上下各有1条黑色的解决方案
- Instant类[java]
- vmbox主机和虚拟机无法共通网络服务 主机无法使用虚拟机的网络服务 虚拟机无法使用主机的网络服务
- qq邮件如何设置html阅读,使用qq邮箱发送html格式的邮件
- 计算机启动 滴的一声,电脑开机时滴的一声是为什么?
热门文章
- selenium禁止弹窗_python:使用带有selenium的firefox时禁用下载弹出窗口
- web版本 开源压测工具_siege--Web性能压测工具
- 二叉树的创建_大多数人都不会手写创建并遍历二叉树,一航这里帮你终结了
- http status 404 – 未找到_从零开始搭建自己的网站004添加404处理页面
- ubuntu修改用户名、计算机名、主目录名
- S3C2440与SDRAM的地址连线分析
- VirtualCopy()操作I/O口 物理地址为什么要移8位
- esp8266 micropython oled_micropython(4):使用ESP8266 控制 oled 屏幕,并显示 helloworld 字符...
- float32精度_PyTorch 1.6来了:新增自动混合精度训练、Windows版开发维护权移交微软...
- 初学者怎样看懂python代码_入门编程(初学者怎样看懂代码)