一:协程

1.什么是协程?
python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关)

2.携程的作用?
程序级别的切换,提升效率 单线程下实现并发

让原本是CPU切换线程   变成  程序切换线程
3.安装第三方模块:在命令行下
pip3 install greenlet
pip3 uninstall greenlet 卸载第三方模块
pip3 list # 列出当前解释器环境下安装的第三方模块

二:greenlet模块(初级模块,实现了保存状态加切换)

首先 先引入的是greenlet模块 然后在引入真正的协程模块
greenlet模块 只是初级模块,只实现了保存状态加切换,没实现遇到io自动切换
  • 代码实现
from greenlet import greenlet

def eat(name):
print(name,'在吃了一口')
g2.switch(name) print(name,'在吃了第二口')
# 执行g2,不需要再传参数了,因为已经传过了,从玩了第二下开始执行
g2.switch() def play(name):
print(name, '玩了一下')
# 执行g1,不需要再传参数了,因为已经传过了,从第二口开始执行
g1.switch() print(name, '玩了第二下') # 类加括号实列化 得到对象
g1=greenlet(eat)
g2=greenlet(play) # 执行
g1.switch('egon')

三: gevent模块(协程模块)

gevent模块,协程模块,遇到io可以自动切换

  • 代码实现
import gevent
import time def eat(name):
print(name, '在吃了一口')
# 遇到了io 自动切换
# 只能用gevent.sleep
gevent.sleep(2)
print(name, '在吃了第二口') def play(name):
print(name, '玩了一下')
# 遇到了io,是gevent的io
gevent.sleep(3)
print(name, '玩了第二下') # 执行前时间
ctime = time.time()
# 内置有返回值 设置协程任务,执行,函数(参数)
res1 = gevent.spawn(eat, 'egon')
res2 = gevent.spawn(play, 'egon') # # 等待协程执行完,在执行主线程
# res1.join()
# res2.join()
gevent.joinall([res1, res2]) # 相当于上面两句
print('主线程')
print(time.time()-ctime)

  • 输出结果
egon 在吃了一口
egon 玩了一下
egon 在吃了第二口
egon 玩了第二下
主线程
3.0269923210144043

1.time 模式协程 遇到io情况

使用原来的time的io,不会切换,并且变成了串行
  • 代码实现
import gevent
import time def eat(name):
print(name, '在吃了一口')
# 遇到了io 自动切换
# 只能用gevent.sleep
time.sleep(2)
print(name, '在吃了第二口') def play(name):
print(name, '玩了一下')
# 遇到了io,是gevent的io
time.sleep(3)
print(name, '玩了第二下') # 执行前时间
ctime = time.time()
# 内置有返回值 设置协程任务,执行,函数(参数)
res1 = gevent.spawn(eat, 'egon')
res2 = gevent.spawn(play, 'egon') # # 等待协程执行完,在执行主线程
# res1.join()
# res2.join()
gevent.joinall([res1, res2]) # 相当于上面两句
print('主线程')
print(time.time()-ctime)

2.解决time无法遇到io切换
  • time无法io切换原因:
线程内切换 用原来的io,会出现它的Gil锁立马就释放了,就切换到另一条线程上执行了,不会再执行异步,而是串行
  • 解决方法:
猴子补丁 : 把原本的io全部替换成gevent的io
  • 猴子补丁作用:
将原本的IO 全部换成不释放Gil锁的IO 所有需要把Gil锁重写一遍 达到遇到io自动切换
  • 代码实现
# 猴子补丁:把原来的io全都替换成gevent的io
from gevent import monkey;monkey.patch_all()
import gevent
import time def eat(name):
print(name, '在吃了一口')
# 遇到了io 自动切换
# 只能用gevent.sleep
time.sleep(2)
print(name, '在吃了第二口')
def play(name):
print(name, '玩了一下')
# 遇到了io,是gevent的io
time.sleep(3)
print(name, '玩了第二下')
# 执行前时间
ctime = time.time()
# 内置有返回值 设置协程任务,执行,函数(参数)
res1 = gevent.spawn(eat, 'egon')
res2 = gevent.spawn(play, 'egon') # # 等待协程执行完,在执行主线程
# res1.join()
# res2.join()
gevent.joinall([res1, res2]) # 相当于上面两句
print('主线程')
print(time.time()-ctime)

四:协程实现TCP服务端并发的效果

并发效果:一个服务端可以同时服务多个客户端
实现:
多进程下开设多线程 多线程下开设协程
  • 服务器


import socket
from gevent import monkey;monkey.patch_all()
from gevent import spawn
def talk(sock):
while True:
try:
# 固定接收客户端数据
data = sock.recv(1024)
# 判断接收数据是否为0
if data == 0: break
print(data)
# 向客户端发送数据
sock.send(data + b'hello baby!')
# 异常捕获
except ConnectionResetError as e:
print(e)
# 接收套字节
sock.close()
break
def servers():
# 套字节
server = socket.socket()
# 绑定ip与端口
server.bind(('127.0.0.1', 8080))
# 连接池
server.listen()
# 通信循环
while True:
# 被动客户端连接 并返回 sock 通信 接收与发送
# addr 客户端地址
sock, addr = server.accept()
# 执行任务 函数(sock)参数
spawn(talk, sock)
# 执行封装
g1 = spawn(servers)
g1.join()
  • 客户端
# 客户端开设几百个线程发消息即可

from threading import Thread, current_thread
from socket import * def client():
# UDP协议
client = socket(AF_INET, SOCK_STREAM)
# 连接服务器ip与port
client.connect(('127.0.0.1', 8080))
n = 0
while True:
# 子线程名子 循环加1
msg = '%s say hello %s' % (current_thread().name, n)
n += 1
# 发送数据 编码
client.send(msg.encode('utf-8'))
# 固定接收数据
data = client.recv(1024)
# 解码
print(data.decode('utf-8')) if __name__ == '__main__':
# 循环执行500个线程
for i in range(500):
# 设置任务
t = Thread(target=client)
# 执行任务
t.start()

五: asyncio(内置协程模块)

内置模块   python 3.4 推出这个模块,python作者主导的

import asyncio
import time
import threading
# 这个函数是协程函数
async def task():
# 获取当前线程的名字
res=threading.current_thread().getName()
print(res)
print('xxx')
# 只要有IO操作,前面加个await
await asyncio.sleep(2)
print('协程执行完成') async def task2():
# 获取当前线程的名字
res=threading.current_thread().getName()
print(res)
print('2222')
await asyncio.sleep(3)
print('222协程执行完成') ctime=time.time()
# 拿到一个循环对象
loop=asyncio.get_event_loop()
# 设置任务
tasks=[task(),task2()]
# 执行任务
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
print(time.time()-ctime)

什么是协程(第三方模块gevent--内置模块asyncio)的更多相关文章

  1. 协程----greenlet模块,gevent模块

    1.协程初识,greenlet模块 2.gevent模块(需要pip安装) 一.协程初识,greenlet模块: 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线 ...

  2. Python之路(第四十七篇) 协程:greenlet模块\gevent模块\asyncio模块

    一.协程介绍 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 协程相比于线程,最大的区别在于 ...

  3. python 线程(其他方法,队列,线程池,协程 greenlet模块 gevent模块)

    1.线程的其他方法 from threading import Thread,current_thread import time import threading def f1(n): time.s ...

  4. 14 并发编程-(协程)-greenlet模块&gevent模块

    1.实现多个任务之间进行切换,yield.greenlet都没有实现检测I/O,greenlet在实现多任务切换下更简单 from greenlet import greenlet def eat(n ...

  5. 并发编程~~~协程~~~greenlet模块, gevent模块

    一 协程 1. 协程: 单线程下的并发,又称微线程,纤程.协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 并发真正的核心: 切换并且保持状态. 开启协程并发的执行,自己的程序把控着C ...

  6. 网络编程基础--协程--greenlet切换---gevent自动识别 IO ---

    协程: 1 单线程来实现并发---协程: 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程, 即协程是由用户程序自己控制调度的 只 ...

  7. 31、Python程序中的协程操作(greenlet\gevent模块)

    一.协程介绍 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是协程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 对比操作系统控制线程的切换,用 ...

  8. Python并发编程协程(Coroutine)之Gevent

    Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate routine的缩写,直接翻译 ...

  9. python网络编程-协程(协程说明,greenlet,gevent)

    一:什么是协程 协程(Coroutine):,又称微线程.协程是一种用户态的轻量级线程.是由用户自己控制,CPU根本不知道协程存在. 协程拥有自己的寄存器上下文和栈. 协程调度切换时,将寄存器上下文和 ...

随机推荐

  1. C/C++ 结构体字节对齐

    在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但是事实上不是如此 ...

  2. Git统计代码变化率

    统计2017-03-01到2017-03-31代码变更率 代码统计命令参考:git log --pretty=tformat: --since ==2017-03-01 --until=2017-03 ...

  3. 1434 区间LCM

    1434 区间LCM 基准时间限制:1 秒 空间限制:131072 KB 一个整数序列S的LCM(最小公倍数)是指最小的正整数X使得它是序列S中所有元素的倍数,那么LCM(S)=X. 例如,LCM(2 ...

  4. 防止 jar 包被反编译

    1.隔离Java程序 最简单的方法就是让用户不能够访问到Java Class程序,这种方法是最根本的方法,具体实现有多种方式.例如,开发人员可以将关键的Java Class放在服务器端,客户端通过访问 ...

  5. <数据结构>图的最小生成树

    目录 最小生成树问题 Prim算法:点贪心 基本思想:类Dijstra 伪代码 代码实现 复杂度分析:O(VlogV + E) kruskal算法:边贪心 基本思想: 充分利用MST性质 伪代码 代码 ...

  6. Java初学者作业——学生成绩等级流程图练习

    返回本章节 返回作业目录 在Word 中编写算法实现学生成绩等级的输出,并绘制对应算法的流程图. 功能要求:输入学生成绩,输出对应成绩等级,输出规则如下: 学生成绩区间 对应成绩等级 [90,100] ...

  7. Java面向对象笔记 • 【第6章 Java常用类】

    全部章节   >>>> 本章目录 6.1 Object类 6.1.1 Object类概述 6.1.2 Object的常用方法 6.1.3 实践练习 6.2 String类和St ...

  8. Log4j2完整XML参考(详细注释说明)

    1.说明 本文提供完整的log4j2.xml配置文件, 供开发中参考使用,可以作为模板, 配置对应实现如下常用的功能: 1.自动检测和重新加载配置,每10分钟(600s)检测一次 2.每个日志文件最大 ...

  9. openmesh - src - trimesh delete and add elements

    openmesh - src - trimesh delete and add elements openmesh 版本 8.1 About 本文主要介绍openmesh的如下接口 add_verte ...

  10. django中写入数据时给密码加密

    方法一.在自定义的form表单中重写save方法: 方法二.使用信号量来实现 1. 在应用的模块下新建signal.py文件 2.编写回调函数,内容如下: 3. 在应用的app.py文件中的ready ...