一:协程

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

2.携程的作用?
  1. 程序级别的切换,提升效率 单线程下实现并发
  2. 让原本是CPU切换线程 变成 程序切换线程
3.安装第三方模块:在命令行下
  1. pip3 install greenlet
  2. pip3 uninstall greenlet 卸载第三方模块
  3. pip3 list # 列出当前解释器环境下安装的第三方模块

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

  1. 首先 先引入的是greenlet模块 然后在引入真正的协程模块
  2. greenlet模块 只是初级模块,只实现了保存状态加切换,没实现遇到io自动切换
  • 代码实现
  1. from greenlet import greenlet
  2. def eat(name):
  3. print(name,'在吃了一口')
  4. g2.switch(name)
  5. print(name,'在吃了第二口')
  6. # 执行g2,不需要再传参数了,因为已经传过了,从玩了第二下开始执行
  7. g2.switch()
  8. def play(name):
  9. print(name, '玩了一下')
  10. # 执行g1,不需要再传参数了,因为已经传过了,从第二口开始执行
  11. g1.switch()
  12. print(name, '玩了第二下')
  13. # 类加括号实列化 得到对象
  14. g1=greenlet(eat)
  15. g2=greenlet(play)
  16. # 执行
  17. g1.switch('egon')

三: gevent模块(协程模块)

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

  • 代码实现
  1. import gevent
  2. import time
  3. def eat(name):
  4. print(name, '在吃了一口')
  5. # 遇到了io 自动切换
  6. # 只能用gevent.sleep
  7. gevent.sleep(2)
  8. print(name, '在吃了第二口')
  9. def play(name):
  10. print(name, '玩了一下')
  11. # 遇到了io,是gevent的io
  12. gevent.sleep(3)
  13. print(name, '玩了第二下')
  14. # 执行前时间
  15. ctime = time.time()
  16. # 内置有返回值 设置协程任务,执行,函数(参数)
  17. res1 = gevent.spawn(eat, 'egon')
  18. res2 = gevent.spawn(play, 'egon')
  19. # # 等待协程执行完,在执行主线程
  20. # res1.join()
  21. # res2.join()
  22. gevent.joinall([res1, res2]) # 相当于上面两句
  23. print('主线程')
  24. print(time.time()-ctime)

  • 输出结果
  1. egon 在吃了一口
  2. egon 玩了一下
  3. egon 在吃了第二口
  4. egon 玩了第二下
  5. 主线程
  6. 3.0269923210144043

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

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

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

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

  1. 并发效果:一个服务端可以同时服务多个客户端
  2. 实现:
  3. 多进程下开设多线程 多线程下开设协程
  • 服务器
  1. import socket
  2. from gevent import monkey;monkey.patch_all()
  3. from gevent import spawn
  4. def talk(sock):
  5. while True:
  6. try:
  7. # 固定接收客户端数据
  8. data = sock.recv(1024)
  9. # 判断接收数据是否为0
  10. if data == 0: break
  11. print(data)
  12. # 向客户端发送数据
  13. sock.send(data + b'hello baby!')
  14. # 异常捕获
  15. except ConnectionResetError as e:
  16. print(e)
  17. # 接收套字节
  18. sock.close()
  19. break
  20. def servers():
  21. # 套字节
  22. server = socket.socket()
  23. # 绑定ip与端口
  24. server.bind(('127.0.0.1', 8080))
  25. # 连接池
  26. server.listen()
  27. # 通信循环
  28. while True:
  29. # 被动客户端连接 并返回 sock 通信 接收与发送
  30. # addr 客户端地址
  31. sock, addr = server.accept()
  32. # 执行任务 函数(sock)参数
  33. spawn(talk, sock)
  34. # 执行封装
  35. g1 = spawn(servers)
  36. g1.join()
  • 客户端
  1. # 客户端开设几百个线程发消息即可
  2. from threading import Thread, current_thread
  3. from socket import *
  4. def client():
  5. # UDP协议
  6. client = socket(AF_INET, SOCK_STREAM)
  7. # 连接服务器ip与port
  8. client.connect(('127.0.0.1', 8080))
  9. n = 0
  10. while True:
  11. # 子线程名子 循环加1
  12. msg = '%s say hello %s' % (current_thread().name, n)
  13. n += 1
  14. # 发送数据 编码
  15. client.send(msg.encode('utf-8'))
  16. # 固定接收数据
  17. data = client.recv(1024)
  18. # 解码
  19. print(data.decode('utf-8'))
  20. if __name__ == '__main__':
  21. # 循环执行500个线程
  22. for i in range(500):
  23. # 设置任务
  24. t = Thread(target=client)
  25. # 执行任务
  26. t.start()

五: asyncio(内置协程模块)

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

  1. import asyncio
  2. import time
  3. import threading
  4. # 这个函数是协程函数
  5. async def task():
  6. # 获取当前线程的名字
  7. res=threading.current_thread().getName()
  8. print(res)
  9. print('xxx')
  10. # 只要有IO操作,前面加个await
  11. await asyncio.sleep(2)
  12. print('协程执行完成')
  13. async def task2():
  14. # 获取当前线程的名字
  15. res=threading.current_thread().getName()
  16. print(res)
  17. print('2222')
  18. await asyncio.sleep(3)
  19. print('222协程执行完成')
  20. ctime=time.time()
  21. # 拿到一个循环对象
  22. loop=asyncio.get_event_loop()
  23. # 设置任务
  24. tasks=[task(),task2()]
  25. # 执行任务
  26. loop.run_until_complete(asyncio.wait(tasks))
  27. loop.close()
  28. 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. nanogui之更新子模块glfw3.3.2踩坑总结

    nanogui源码下载: A . https://github.com/wjakob/nanogui B . https://github.com/dalerank/nanogui B是fork的A, ...

  2. 【LeetCode】174. Dungeon Game 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划 日期 题目地址:https://leetc ...

  3. 【LeetCode】149. Max Points on a Line 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典+最大公约数 日期 题目地址:https://l ...

  4. Buy Tickets(poj2828)

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 17416   Accepted: 8646 Desc ...

  5. 【机器学*】k*邻算法-01

    k临*算法(解决分类问题): 已知数据集,以及该数据对应类型 给出一个数据x,在已知数据集中选择最接*x的k条数据,根据这k条数据的类型判断x的类型 具体实现: from numpy import * ...

  6. hisql 新功能 支持一套sql在不同数据库执行

    目前流行的ORM框架如果需要动态的拼接查询语句,只能用原生的sql进行拼接,无法跨不同数据库执行.hisql推出新的语法一套语句可以在不同的数据库执行 传统ORM框架最大的弊端就是完全要依赖于实体用l ...

  7. JMeter跨线程,怎么定义全局变量,跨线程使用变量?

    JMeter跨线程时,怎么定义全局变量,跨线程使用此变量? 通过函数助手,获取到设置变量的语法脚本 2.通过Bean shell Sampler取样器,定义全局变量 3.定义好全局变量,可以调用,调用 ...

  8. Django在使用logging日志模块时报错无法操作文件 logging error Permission Error [WinError 32]

    产生原因: 这个问题只会在开发的时候遇到,而且配置是写入到setting.py配置文件,我们定义了日志文件大小,当日志满了的时候,这时候就会遇到这个问题, 因为在使用Pycharm运行django的时 ...

  9. 初识python: 斐波拉契数(生成器获取)

    使用  生成器(yield) 获取斐波拉契数. 代码如下: def fun(n): a,b,c = 0,0,1 while a < n: yield b # b, c = c, b + c 以下 ...

  10. CAP原理详解

    转载 https://blog.csdn.net/u013332124/article/details/82874178 文章目录 一.CAP原理介绍 对CAP原理的一些常见的理解误区 二.CAP原理 ...