day10---异步I/O,gevent协程
协程
协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
协程的好处:
- 无需线程上下文切换的开销
- 无需原子操作锁定及同步的开销
- 方便切换控制流,简化编程模型
- 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。
缺点:
- 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
- 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序
使用yield实现协程操作例子
- import time
- import queue
- def consumer(name):
- print("--->starting eating baozi...")
- while True:
- new_baozi = yield
- print("[%s] is eating baozi %s" % (name,new_baozi))
- #time.sleep(1)
- def producer():
- r = con.__next__()
- r = con2.__next__()
- n = 0
- while n < 5:
- n +=1
- con.send(n)
- con2.send(n)
- print("\033[32;1m[producer]\033[0m is making baozi %s" %n )
- if __name__ == '__main__':
- con = consumer("c1")
- con2 = consumer("c2")
- p = producer()
- #!/usr/bin/env python
- #-*- coding:utf-8 -*-
- # Author:DCC
- from greenlet import greenlet
- import gevent
- '''
- def test1():
- print(12)
- gr2.switch()
- print(34)
- gr2.switch()
- def test2():
- print(56)
- gr1.switch()
- print(78)
- gr1 = greenlet(test1)
- gr2 = greenlet(test2)
- gr1.switch()
- '''
- def foo():
- print("Running in foo")
- gevent.sleep(4)
- print("switch to foo")
- def bar():
- print("Running in bar")
- gevent.sleep(1)
- print("已经调到bar")
- def func3():
- print("Running in func3")
- gevent.sleep(2)
- print("func3 again")
- gevent.joinall([
- gevent.spawn(foo),
- gevent.spawn(bar),
- gevent.spawn(func3),
- ])
遇到IO阻塞时会自动切换任务
爬虫
- #!/usr/bin/env python
- #-*- coding:utf-8 -*-
- # Author:DCC
- from urllib import request
- import gevent,time
- from gevent import monkey
- monkey.patch_all()#把当前程序的所有的IO操作单独做上标记
- #之前 gevent是不是捕获 urllib的IO操作的,所有,无法进行切换
- def f(url):
- print("GET: %s" % url)
- resp = request.urlopen(url)
- data = resp.read()
- print("%d bytes received from %s." % (len(data),url))
- urls = [
- "https://www.python.org/",
- "https://www.yahoo.com/",
- "https://github.com/"
- ]
- start_time = time.time()
- for url in urls:
- f(url)
- print("同步cost",time.time()-start_time)
- async_start_time = time.time()
- gevent.joinall([
- gevent.spawn(f,"https://www.python.org/"),
- gevent.spawn(f,"https://www.yahoo.com/"),
- gevent.spawn(f,"https://github.com/"),
- ])
- print("异步cost",time.time()-async_start_time)
通过gevent实现单线程下的多socket并发
server side
- import sys
- import socket
- import time
- import gevent
- from gevent import socket,monkey
- monkey.patch_all()
- def server(port):
- s = socket.socket()
- s.bind(('0.0.0.0', port))
- s.listen(500)
- while True:
- cli, addr = s.accept()
- gevent.spawn(handle_request, cli)
- def handle_request(conn):
- try:
- while True:
- data = conn.recv(1024)
- print("recv:", data)
- conn.send(data)
- if not data:
- conn.shutdown(socket.SHUT_WR)
- except Exception as ex:
- print(ex)
- finally:
- conn.close()
- if __name__ == '__main__':
- server(8001)
client side
- import socket
- HOST = 'localhost' # The remote host
- PORT = 8001 # The same port as used by the server
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((HOST, PORT))
- while True:
- msg = bytes(input(">>:"),encoding="utf8")
- s.sendall(msg)
- data = s.recv(1024)
- #print(data)
- print('Received', repr(data))
- s.close()
day10---异步I/O,gevent协程的更多相关文章
- Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)
一.进程: 1.语法 2.进程间通讯 3.进程池 二.Gevent协程 三.Select\Poll\Epoll异步IO与事件驱动 一.进程: 1.语法 简单的启动线程语法 def run(name): ...
- Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)
Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...
- python2.0_s12_day9_协程&Gevent协程
Python之路,Day9 - 异步IO\数据库\队列\缓存 本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 协程 1.协程,又 ...
- gevent协程、select IO多路复用、socketserver模块 改造多用户FTP程序例子
原多线程版FTP程序:http://www.cnblogs.com/linzetong/p/8290378.html 只需要在原来的代码基础上稍作修改: 一.gevent协程版本 1. 导入geven ...
- python并发编程之gevent协程(四)
协程的含义就不再提,在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块.由于协程对于操作系统是无感知的,所以其切换需要程序员自己去完成. 系列文章 python并发编程 ...
- 什么是协程?与线程和进程对比优劣在哪?gevent协程示例代码
协程 协程,又称微线程,纤程.英文名Coroutine..一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在 ...
- PHP下的异步尝试三:协程的PHP版thunkify自动执行器
PHP下的异步尝试系列 如果你还不太了解PHP下的生成器和协程,你可以根据下面目录翻阅 PHP下的异步尝试一:初识生成器 PHP下的异步尝试二:初识协程 PHP下的异步尝试三:协程的PHP版thunk ...
- Python Gevent协程自动切换IO
Gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程. Gr ...
- python gevent 协程
简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...
随机推荐
- HTML5 --照抄书里的代码但函数无法执行、求分析( Uncaught ReferenceError: xxx is not defined)
在js文件里写一个方法传参数: moveElement(id,name,price) { alert("id:"+id+"name:"+name+"p ...
- R语言画图,根据正负值画不同颜色,并且画水平线或者垂直线
col=ifelse(x<0, "blue", "red") #如果x值为负值,用蓝色表示,反之,用红色表示 abline(v=0,col="g ...
- python学习之——操作浏览器
使用selenium的webdriver框架,对浏览器的常规操作,如下~~ #coding=utf-8 from selenium import webdriver import time from ...
- 关于for循环删除数组内容出现的问题
昨天用for循环进行数组去重的时候出现的问题, 首先,用双重for循环把前一个和所有后面的元素进行比较,如果相等则删除. 但是,如果数组里面有三个以上连续相等的元素的时候,就会出现问题. var ar ...
- C++关于文件的读写(续)
上次,我们探讨了C++关于文件的读操作,这次继续写操作.写,顾名思义,就是把我们自己的东西放到文件中去. 我们举一个简单的例子,就不在乎它的排版问题了. #include<iostream> ...
- 关于String中+与StringBuilder的问题
字符串连接可以通过两种方法实现,其中一种是在Java中提供的一个StringBuilder类(这个类只在J2SE5及以上版本提供,以前的版本使用StringBuffer类). 字符串是Java程序 ...
- c# HttpWebRequest 与 HttpWebResponse
如果你想做一些,抓取,或者是自动获取的功能,那么就跟我一起来学习一下Http请求吧.本文章会对Http请求时的Get和Post方式进行详细的说明,在请求时的参数怎么发送,怎么带Cookie,怎么设置证 ...
- DbProviderFactory .net数据库工厂模式
http://kb.cnblogs.com/page/72789/ 工厂模式 http://www.cnblogs.com/Ruiky/archive/2012/04/19/2456784.html ...
- win7/win8远程桌面 server 2003 卡的问题
原因在于从vista开始,微软在TCP/IP协议栈里新加了一个叫做“Window Auto-Tuning”的功能.这个功能本身的目的是为了让操作系统根据网络的实时性能(比如响应时间)来动态调整网络上传 ...
- 在SqlServer查询分析器里 访问远程数据库 进行数据查询更新等操作(openrowset)
启用Ad Hoc Distributed Queries: exec sp_configure 'show advanced options',1 reconfigure exec sp_config ...