协程-遇到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
