协程-遇到I/O自动切换
2018-06-17 23:50:15来源:未知 阅读 ()
参考博客: http://www.cnblogs.com/alex3714/articles/5248247.html
一、前言
Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。
二、Gevent
import gevent def func1(): print('running in func1...') gevent.sleep(2) # I/O中断2秒 print('Explicit context switch to func1 again...') def func2(): print('Explicit context func2...') gevent.sleep(1) print('Implicit context switch to func2 again...') gevent.joinall([ gevent.spawn(func1), gevent.spawn(func2), ])
import gevent def func1(): print('running in func1...') gevent.sleep(2) print('Explicit context switch to func1 again...') def func2(): print('Explicit context func2...') gevent.sleep(1) print('Implicit context switch to func1 again...') def func3(): print('running in func3...') gevent.sleep(0) # 表示中断,没有时间 print('running func3 again...') gevent.joinall([ gevent.spawn(func1), gevent.spawn(func2), gevent.spawn(func3), ])
三、遇到I/O阻塞时自动切换任务
简单的gevent并发爬网页
# -*- coding: UTF-8 -*- from urllib import request import time from gevent import monkey import gevent monkey.patch_all() # gevent并不能识别urllib 的I/O中断,monkey.patch_all会给所有I/O中断做标签 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/' ] time_start = time.time() for url in urls: f(url) print('同步take %s seconds' % (time.time() - time_start)) # 异步处理 async_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('异步take %s seconds' % (time.time() - async_time))
结果:
Get: https://www.python.org/ 48956 bytes received from https://www.python.org/. Get: https://www.yahoo.com/ 517389 bytes received from https://www.yahoo.com/. Get: https://github.com/ 51473 bytes received from https://github.com/. 同步take 4.6533966064453125 seconds Get: https://www.python.org/ Get: https://www.yahoo.com/ Get: https://github.com/ 48956 bytes received from https://www.python.org/. 521617 bytes received from https://www.yahoo.com/. 51473 bytes received from https://github.com/. 异步take 1.916191816329956 seconds # 可以看到两者之间时间差别还是很大的
如果没有monkey.patch_all(),程序也能正常运行,但是同步和异步时间基本没有差别,因为gevent并不知道urllib的I/O中断,所以也不会自动切换,所以哪怕使用了gevent,程序也是同步执行(串行)。而monkey.patch_all()就可以为所有urllib中的I/O中断做标记,gevent遇到这些中断就会自动切换,执行其他没有I/O操作的程序。
四、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()
# 并发100 个socket连接 import socket import threading def sock_conn(): client = socket.socket() client.connect(("localhost",8001)) count = 0 while True: #msg = input(">>:").strip() #if len(msg) == 0:continue client.send( ("hello %s" %count).encode("utf-8")) data = client.recv(1024) print("[%s]recv from server:" % threading.get_ident(),data.decode()) #结果 count +=1 client.close() for i in range(100): t = threading.Thread(target=sock_conn) t.start()
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 利用python自动生成verilog模块例化模板 2019-08-13
- 一篇文章教你使用Python自动赚取支付宝积分,网友:发家致富 2019-07-24
- python自动化测试之DDT数据驱动 2019-07-24
- python+selenium实现自动化百度搜索关键词 2019-07-24
- RobotFramework + HTTP接口自动化实现 2019-07-24
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash