Day 42 协程. IO 并发
一、什么是协程?
是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。
协程相比于线程切换效率更快了.
本质是线程
能够在多个任务之间切换来节省一些IO时间.
协程中任务之间的切换时间开销要远远小于进程线程之间的切换.
真正的协程模块就是使用greenlet完成切换的.
进程和协程的任务切换由操作系统完成.
协程任务之间的切换由程序完成.
协程任务之间的切换由程序代码完成 , 只有遇到协程模块能识别的io操作的时候程序才会进行任务切换,实现并发的效果。
协程:
能够在一个线程中实现并发效果的概念.
能够规避一些任务中的IO操作.
在任务的执行过程中,检测到IO就切换到其他任务.
在两个任务之间来回切换数据(简单的协程的概念)
# import time
# def consumer():
# while True:
# x = yield
# time.sleep(1)
# print('处理了数据 :',x)
#
# def producer():
# c = consumer()#生成一个生成器对象
# next(c) #每次next返回一个值
# for i in range(10):
# time.sleep(1)
# print('生产了数据 :',i)
# c.send(i)
# producer()
输出结果:虽然实现了切换,但是没有节约IO时间.
D:\PycharmProjects\test\venv\Scripts\python.exe D:/parcharm/42.py
生产了数据 : 0
处理了数据 : 0
生产了数据 : 1
处理了数据 : 1
生产了数据 : 2
处理了数据 : 2
生产了数据 : 3
处理了数据 : 3
生产了数据 : 4
处理了数据 : 4
生产了数据 : 5
处理了数据 : 5
生产了数据 : 6
处理了数据 : 6
生产了数据 : 7
处理了数据 : 7
生产了数据 : 8
处理了数据 : 8
生产了数据 : 9
处理了数据 : 9
二 、安装 gevent和greenlet
查看安装状态
真正的协程模块就是使用greenlet完成的切换
from greenlet import greenlet
def eat():
print("吃开始")
g2.switch()
print("吃完了")
g2.switch()
def play():
print("开始玩")
g1.switch()
print('玩完了')
g1 =greenlet(eat)
g2 =greenlet(play)
g1.switch()
打印结果:
D:\PycharmProjects\test\venv\Scripts\python.exe D:/parcharm/44.py
吃开始
开始玩
吃完了
玩完了
协程能够在一个线程中实现并发效果的概念。
能够规避一些任务中的IO操作
在任务的执行过程中,检测到IO就切换到其他的任务.
三、爬虫的例子(正则有基础.)
请求过程中的IO等待
import requests #需要pip安装的。
from urllib.request import urlopen#内置的模块
url='http://www.baidu.com'
res1 =urlopen(url)
res2 = requests.get(url)
print(res1)
print(res2) print(res1.read().decode('utf-8'))# 有格式的
print(res2.content.decode('utf-8'))#无格式的。
爬虫 (结果是一起显示出来的。)
gevent 用在爬虫和socket的编程中会用的到.
gevent是python的一个并发框架,以微线程greenlet为核心,使用了epoll事件监听机制以及诸多其他优化而变得高效.而且其中有个monkey类,
将现有基于Python线程直接转化为greenlet(类似于打patch).他和线程框架性能比高大概4倍(看下图,是gevent和paste的对比):
from gevent import monkey;monkey.patch_all()
import gevent
from urllib.request import urlopen
def get_url(url):
response = urlopen(url)
content = response.read().decode('utf-8')
return len(content) g1 =gevent.spawn(get_url,'http://www.baidu.com')
g2 =gevent.spawn(get_url,'http://www.sohu.com')
g3 =gevent.spawn(get_url,'http://www.hao123.com')
g4 =gevent.spawn(get_url,'http://www.cnblog.com')
g5 =gevent.spawn(get_url,'http://www.cnblog.com')
gevent.joinall([g1,g2,g3,g4,g5])
print(g1.value)
print(g2.value)
print(g3.value)
print(g4.value)
print(g5.value)
打印结果
D:\PycharmProjects\test\venv\Scripts\python.exe D:/parcharm/44.py
114439
185037
523375
1887
1887
协程实现socket的案例
协程间的切换是代码级别的,
线程间切换时操作系统级别的。
Server端
from gevent import monkey;monkey.patch_all()
import socket
import gevent
def talk(conn):
conn.send(b'hello')
print(conn.recv(1024).decode('utf-8'))
conn.close() sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
while True:
conn,addr = sk.accept()
gevent.spawn(talk,conn)
sk.close()
client端
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
print(sk.recv(1024))
msg = input('>>>').encode('utf-8')
sk.send(msg)
sk.close()
四 IO模型.
blocking IO 阻塞IO
nonblocking IO 非阻塞IO
IO multiplexing IO 多路复用
asynchronous IO 异步 IO
Blocking IO 阻塞IO
同步:同步提交一个任务之后要等待这个任务执行完毕.
异步只管提交任务,
Day 42 协程. IO 并发的更多相关文章
- 协程IO多路复用
协程:单线程下实现并发并发:伪并行,遇到IO就切换,单核下多个任务之间切换执行,给你的效果就是貌似你的几个程序在同时执行.提高效率任务切换 + 保存状态并行:多核cpu,真正的同时执行串行:一个任务执 ...
- 理解Go协程与并发
协程 Go语言里创建一个协程很简单,使用go关键字就可以让一个普通方法协程化: package main import ( "fmt" "time" ) fun ...
- day 35 协程 IO多路复用
0.基于socket发送Http请求 import socket import requests # 方式一 ret = requests.get('https://www.baidu.com/s?w ...
- 数据库 tcp协程实现并发 回调函数
数据库 tcp协程实现并发 回顾 一.回顾 进程池,线程池,回调函数 # from gevent import monkey;monkey.patch_all() #补丁 from gevent im ...
- 理解Go协程与并发(转)
理解Go协程与并发 协程 Go语言里创建一个协程很简单,使用go关键字就可以让一个普通方法协程化: Copy package main import ( "fmt" " ...
- 11.python3标准库--使用进程、线程和协程提供并发性
''' python提供了一些复杂的工具用于管理使用进程和线程的并发操作. 通过应用这些计数,使用这些模块并发地运行作业的各个部分,即便是一些相当简单的程序也可以更快的运行 subprocess提供了 ...
- 05网络并发 ( GIL+进程池与线程池+协程+IO模型 )
目录 05 网络并发 05 网络并发
- 协程+IO切换实现并发
from gevent import monkey # 以后代码中遇到IO都会自动执行greenlet的switch进行切换 monkey.patch_all() import requests im ...
- Python学习笔记整理总结【网络编程】【线程/进程/协程/IO多路模型/select/poll/epoll/selector】
一.socket(单链接) 1.socket:应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socke ...
随机推荐
- 2-string相关函数
string真的很好用,希望通过逐步的学习逐渐掌握的string的用法: 1. append() -- 在字符串的末尾添加字符 2. find() -- 在字符串中查找字符串 4. insert() ...
- Oracle 进入数据库 新增用户 修改密码方法
1.以管理员身份进入 SQL plus 2.输入:sys/manager as sysdba 3.新增用户: 创建新用户: create user 用户名 identified by 密码; 解锁用户 ...
- Castle ActiveRecord学习(四)延迟加载、分页查询、where条件
一.延迟加载 //用户发布的主题,一对多:Table:外键表:ColumnKey:外键:Lazy:延迟加载:Cascade:级联操作(级联删除) [HasMany(typeof(ThemeInfo), ...
- 在cygwin中执行bat文件
在cygwin中执行bat文件 #!/bin/bash dir_gen_image_bat=C:/MinGW/msys/1.0/home/Administrator/feitian_audio/FOT ...
- 一篇文章Tornado快速入门
Tornado是一个PythonWeb框架.一个异步网络库.通过使用非阻塞网络I/O,Tornado能够处理数以千计的连接,这意味着对于实时Web服务来说,Tornado是一个理想的Web框架. 作为 ...
- java Exception in thread "main" java.lang.NoClassDefFoundError: main (wrong name: pm/main)
javac main.java 编译后没有问题 java main 出现下面在问题: Exception in thread "main" java.lang.NoClassDef ...
- Jigloo 下载 安装 GUI
这个需要授权,一直不能解决!! 网上找了很多,都觉不能访问,这个可以用Eclipse直接更新的 http://www.cloudgardensoftware.com/jigloo/update-sit ...
- k8s容器挂载配置文件
1.新建ConfigMap apiVersion: v1 kind: ConfigMap metadata: name: test-conf namespace: default labels: na ...
- SQL之mysql常用操作语句(入门级)
1.进入数据库: mysql -u root -p mysql -h localhost -u root -p database_name 2.列出数据库 show databases; 3.选择数据 ...
- C++之类和对象的使用(二)
析构函数 析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前完成一系列清理工作,使这部分内存可以被程序分配给新对象使用.对象生命周期结束,程序就自动执行析构函数来完成这些工作. 析构函数是一种 ...