一、什么是协程?

是单线程下的并发,又称微线程,纤程。英文名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 并发的更多相关文章

  1. 协程IO多路复用

    协程:单线程下实现并发并发:伪并行,遇到IO就切换,单核下多个任务之间切换执行,给你的效果就是貌似你的几个程序在同时执行.提高效率任务切换 + 保存状态并行:多核cpu,真正的同时执行串行:一个任务执 ...

  2. 理解Go协程与并发

    协程 Go语言里创建一个协程很简单,使用go关键字就可以让一个普通方法协程化: package main import ( "fmt" "time" ) fun ...

  3. day 35 协程 IO多路复用

    0.基于socket发送Http请求 import socket import requests # 方式一 ret = requests.get('https://www.baidu.com/s?w ...

  4. 数据库 tcp协程实现并发 回调函数

    数据库 tcp协程实现并发 回顾 一.回顾 进程池,线程池,回调函数 # from gevent import monkey;monkey.patch_all() #补丁 from gevent im ...

  5. 理解Go协程与并发(转)

    理解Go协程与并发   协程 Go语言里创建一个协程很简单,使用go关键字就可以让一个普通方法协程化: Copy package main import ( "fmt" " ...

  6. 11.python3标准库--使用进程、线程和协程提供并发性

    ''' python提供了一些复杂的工具用于管理使用进程和线程的并发操作. 通过应用这些计数,使用这些模块并发地运行作业的各个部分,即便是一些相当简单的程序也可以更快的运行 subprocess提供了 ...

  7. 05网络并发 ( GIL+进程池与线程池+协程+IO模型 )

    目录 05 网络并发 05 网络并发

  8. 协程+IO切换实现并发

    from gevent import monkey # 以后代码中遇到IO都会自动执行greenlet的switch进行切换 monkey.patch_all() import requests im ...

  9. Python学习笔记整理总结【网络编程】【线程/进程/协程/IO多路模型/select/poll/epoll/selector】

    一.socket(单链接) 1.socket:应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socke ...

随机推荐

  1. MongoDB安装(一)

    详细图解,记录 win7 64 安装mongo数据库的过程.安装的版本是 MongoDB-win32-x86_64-2008plus-ssl-3.4.1-signed. 示例版本:mongodb-wi ...

  2. php 使用PHPExcel 导出数据为Excel

    <?php require_once 'PHPExcel/Classes/PHPExcel.php'; /** * 导出数据为Excel * @param array $fieldArr 标题数 ...

  3. 使用PHP-GTK编写一个windows桌面应用程序

    PHP-GTK的下载地址:http://gtk.php.net/download.php?language=en-US, 猿哥选择了最新版本(beta版),可能有人会问我们为啥不选最新的stable版 ...

  4. 【转】MEF程序设计指南五:迟延(Lazy)加载导出部件(Export Part)与元数据(Metadata)

    MEF中使用导出与导入,实质上就是对一个对象的实例化的过程,通过MEF的特性降低了对象的直接依赖,从而让系统的设计达到一种高灵活.高扩展性的效果.在具体的设计开发中,存在着某些对象是不需要在系统运行或 ...

  5. Vue.js 生命周期的应用

    生命周期示意图 值得注意的几个钩子函数 activated 类型:Function 详细: keep-alive 组件激活时调用. 该钩子在服务器端渲染期间不被调用. 参考: 构建组件 - keep- ...

  6. Jmeter如何把CSV文件的路径设置成一个变量,且变量的值是一个相对路径

    首先,在Jmeter中,通过User Defined Variables设置一个变量用来存储CSV文件所在文件夹的相对路径 备注: 这个相对路径前面不要加.\ 加了的话在运行的时候会报错,提示找不到那 ...

  7. 电商类Web原型制作分享——聚美优品

    这是一家化妆品限时特卖商城.作为美妆电商类网站的佼佼者,网站以用户体验为核心,画面主色调符合女性消费者审美.排版整齐,布局合理.网站用弹出面板实现点击弹出内容,鼠标悬停文字按钮颜色改变等交互效果. 本 ...

  8. 构造函数constructor 与析构函数destructor(二)

    (1)转换构造函数 转换构造函数的定义:转换构造函数就是把普通的内置类型转换成类类型的构造函数,这种构造函数只有一个参数.只含有一个参数的构造函数,可以作为两种构造函数,一种是普通构造函数用于初始化对 ...

  9. 2018.09.09 cogs693. Antiprime数(搜索)

    传送门 看完题发现很sb. 前10个质数乘起来已经超出题目范围了. 因此只用搜索前几个质数每个的次数比较谁的因数的就行了. 代码: #include<iostream> #define l ...

  10. WCF客户端第一请求server特别慢,解决办法

    最近开发WCF应用的客户端,第一连接WCF后,请求数据返回的速度特别慢,不知道原因如何.最后改了下系统生成的APP.Config文件就好了,原来没有useDefaultWebProxy的选项,没有的时 ...