协程

协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程

协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:

协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。

协程的好处:

  • 无需线程上下文切换的开销
  • 无需原子操作锁定及同步的开销
  • 方便切换控制流,简化编程模型
  • 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

缺点:

  • 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
  • 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

使用yield实现协程操作例子    

  1. import time
  2. import queue
  3. def consumer(name):
  4. print("--->starting eating baozi...")
  5. while True:
  6. new_baozi = yield
  7. print("[%s] is eating baozi %s" % (name,new_baozi))
  8. #time.sleep(1)
  9.  
  10. def producer():
  11.  
  12. r = con.__next__()
  13. r = con2.__next__()
  14. n = 0
  15. while n < 5:
  16. n +=1
  17. con.send(n)
  18. con2.send(n)
  19. print("\033[32;1m[producer]\033[0m is making baozi %s" %n )
  20.  
  21. if __name__ == '__main__':
  22. con = consumer("c1")
  23. con2 = consumer("c2")
  24. p = producer()
  1. #!/usr/bin/env python
  2. #-*- coding:utf-8 -*-
  3. # Author:DCC
  4. from greenlet import greenlet
  5. import gevent
  6. '''
  7. def test1():
  8. print(12)
  9. gr2.switch()
  10. print(34)
  11. gr2.switch()
  12. def test2():
  13. print(56)
  14. gr1.switch()
  15. print(78)
  16. gr1 = greenlet(test1)
  17. gr2 = greenlet(test2)
  18. gr1.switch()
  19. '''
  20. def foo():
  21. print("Running in foo")
  22. gevent.sleep(4)
  23. print("switch to foo")
  24. def bar():
  25. print("Running in bar")
  26. gevent.sleep(1)
  27. print("已经调到bar")
  28. def func3():
  29. print("Running in func3")
  30. gevent.sleep(2)
  31. print("func3 again")
  32.  
  33. gevent.joinall([
  34. gevent.spawn(foo),
  35. gevent.spawn(bar),
  36. gevent.spawn(func3),
  37. ])

遇到IO阻塞时会自动切换任务

爬虫

  1. #!/usr/bin/env python
  2. #-*- coding:utf-8 -*-
  3. # Author:DCC
  4. from urllib import request
  5. import gevent,time
  6. from gevent import monkey
  7. monkey.patch_all()#把当前程序的所有的IO操作单独做上标记
  8. #之前 gevent是不是捕获 urllib的IO操作的,所有,无法进行切换
  9. def f(url):
  10. print("GET: %s" % url)
  11. resp = request.urlopen(url)
  12. data = resp.read()
  13. print("%d bytes received from %s." % (len(data),url))
  14.  
  15. urls = [
  16. "https://www.python.org/",
  17. "https://www.yahoo.com/",
  18. "https://github.com/"
  19. ]
  20. start_time = time.time()
  21. for url in urls:
  22. f(url)
  23. print("同步cost",time.time()-start_time)
  24. async_start_time = time.time()
  25. gevent.joinall([
  26. gevent.spawn(f,"https://www.python.org/"),
  27. gevent.spawn(f,"https://www.yahoo.com/"),
  28. gevent.spawn(f,"https://github.com/"),
  29. ])
  30. print("异步cost",time.time()-async_start_time)

通过gevent实现单线程下的多socket并发

server side

  1. import sys
  2. import socket
  3. import time
  4. import gevent
  5.  
  6. from gevent import socket,monkey
  7. monkey.patch_all()
  8.  
  9. def server(port):
  10. s = socket.socket()
  11. s.bind(('0.0.0.0', port))
  12. s.listen(500)
  13. while True:
  14. cli, addr = s.accept()
  15. gevent.spawn(handle_request, cli)
  16.  
  17. def handle_request(conn):
  18. try:
  19. while True:
  20. data = conn.recv(1024)
  21. print("recv:", data)
  22. conn.send(data)
  23. if not data:
  24. conn.shutdown(socket.SHUT_WR)
  25.  
  26. except Exception as ex:
  27. print(ex)
  28. finally:
  29. conn.close()
  30. if __name__ == '__main__':
  31. server(8001)

client side 

  1. import socket
  2.  
  3. HOST = 'localhost' # The remote host
  4. PORT = 8001 # The same port as used by the server
  5. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6. s.connect((HOST, PORT))
  7. while True:
  8. msg = bytes(input(">>:"),encoding="utf8")
  9. s.sendall(msg)
  10. data = s.recv(1024)
  11. #print(data)
  12.  
  13. print('Received', repr(data))
  14. s.close()

day10---异步I/O,gevent协程的更多相关文章

  1. Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)

    一.进程: 1.语法 2.进程间通讯 3.进程池 二.Gevent协程 三.Select\Poll\Epoll异步IO与事件驱动 一.进程: 1.语法 简单的启动线程语法 def run(name): ...

  2. Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)

    Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...

  3. python2.0_s12_day9_协程&Gevent协程

    Python之路,Day9 - 异步IO\数据库\队列\缓存 本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 协程 1.协程,又 ...

  4. gevent协程、select IO多路复用、socketserver模块 改造多用户FTP程序例子

    原多线程版FTP程序:http://www.cnblogs.com/linzetong/p/8290378.html 只需要在原来的代码基础上稍作修改: 一.gevent协程版本 1. 导入geven ...

  5. python并发编程之gevent协程(四)

    协程的含义就不再提,在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块.由于协程对于操作系统是无感知的,所以其切换需要程序员自己去完成. 系列文章 python并发编程 ...

  6. 什么是协程?与线程和进程对比优劣在哪?gevent协程示例代码

      协程 协程,又称微线程,纤程.英文名Coroutine..一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在 ...

  7. PHP下的异步尝试三:协程的PHP版thunkify自动执行器

    PHP下的异步尝试系列 如果你还不太了解PHP下的生成器和协程,你可以根据下面目录翻阅 PHP下的异步尝试一:初识生成器 PHP下的异步尝试二:初识协程 PHP下的异步尝试三:协程的PHP版thunk ...

  8. Python Gevent协程自动切换IO

    Gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程. Gr ...

  9. python gevent 协程

    简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...

随机推荐

  1. HTML5 --照抄书里的代码但函数无法执行、求分析( Uncaught ReferenceError: xxx is not defined)

    在js文件里写一个方法传参数: moveElement(id,name,price) { alert("id:"+id+"name:"+name+"p ...

  2. R语言画图,根据正负值画不同颜色,并且画水平线或者垂直线

    col=ifelse(x<0, "blue", "red") #如果x值为负值,用蓝色表示,反之,用红色表示 abline(v=0,col="g ...

  3. python学习之——操作浏览器

    使用selenium的webdriver框架,对浏览器的常规操作,如下~~ #coding=utf-8 from selenium import webdriver import time from ...

  4. 关于for循环删除数组内容出现的问题

    昨天用for循环进行数组去重的时候出现的问题, 首先,用双重for循环把前一个和所有后面的元素进行比较,如果相等则删除. 但是,如果数组里面有三个以上连续相等的元素的时候,就会出现问题. var ar ...

  5. C++关于文件的读写(续)

    上次,我们探讨了C++关于文件的读操作,这次继续写操作.写,顾名思义,就是把我们自己的东西放到文件中去. 我们举一个简单的例子,就不在乎它的排版问题了. #include<iostream> ...

  6. 关于String中+与StringBuilder的问题

      字符串连接可以通过两种方法实现,其中一种是在Java中提供的一个StringBuilder类(这个类只在J2SE5及以上版本提供,以前的版本使用StringBuffer类). 字符串是Java程序 ...

  7. c# HttpWebRequest 与 HttpWebResponse

    如果你想做一些,抓取,或者是自动获取的功能,那么就跟我一起来学习一下Http请求吧.本文章会对Http请求时的Get和Post方式进行详细的说明,在请求时的参数怎么发送,怎么带Cookie,怎么设置证 ...

  8. DbProviderFactory .net数据库工厂模式

    http://kb.cnblogs.com/page/72789/  工厂模式 http://www.cnblogs.com/Ruiky/archive/2012/04/19/2456784.html ...

  9. win7/win8远程桌面 server 2003 卡的问题

    原因在于从vista开始,微软在TCP/IP协议栈里新加了一个叫做“Window Auto-Tuning”的功能.这个功能本身的目的是为了让操作系统根据网络的实时性能(比如响应时间)来动态调整网络上传 ...

  10. 在SqlServer查询分析器里 访问远程数据库 进行数据查询更新等操作(openrowset)

    启用Ad Hoc Distributed Queries: exec sp_configure 'show advanced options',1 reconfigure exec sp_config ...