协程-遇到I/O自动切换
参考博客: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()
协程-遇到I/O自动切换的更多相关文章
- 【python】-- 协程介绍及基本示例、协程遇到IO操作自动切换、协程(gevent)并发爬网页
协程介绍及基本示例 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是协程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他 ...
- 利用协程爬网页,自动切换io 精典案例:
首先Python提供的协程库gevent好像并不能知道那些程序使用了io 所以要加一个补丁,mondey,以下同步和异步各爬一次的案例 : , from urllib import requesti ...
- flask之分析线程和协程
flask之分析线程和协程 01 思考:每个请求之间的关系 我们每一个请求进来的时候都开一个进程肯定不合理,那么如果每一个请求进来都是串行的,那么根本实现不了并发,所以我们假定每一个请求进来使用的是线 ...
- Flask 之分析线程和协程
目录 flask之分析线程和协程 01 思考:每个请求之间的关系 02 threading.local 03 通过字典自定义threading.local 04 通过setattr和getattr实现 ...
- 网络编程基础--协程--greenlet切换---gevent自动识别 IO ---
协程: 1 单线程来实现并发---协程: 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程, 即协程是由用户程序自己控制调度的 只 ...
- Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)
Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...
- 并发异步编程之争:协程(asyncio)到底需不需要加锁?(线程/协程安全/挂起/主动切换)Python3
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_208 协程与线程向来焦孟不离,但事实上是,线程更被我们所熟知,在Python编程领域,单核同时间内只能有一个线程运行,这并不是什么 ...
- 异步、+回调机制、线程queue、线程Event、协程、单线程实现遇到IO切换
# from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor # import requests # import o ...
- PHP下的异步尝试三:协程的PHP版thunkify自动执行器
PHP下的异步尝试系列 如果你还不太了解PHP下的生成器和协程,你可以根据下面目录翻阅 PHP下的异步尝试一:初识生成器 PHP下的异步尝试二:初识协程 PHP下的异步尝试三:协程的PHP版thunk ...
随机推荐
- Fedora 28 UEFI模式安装过程记录
这次的折腾是个意外.不过还是要记录一下. 多次做启动盘,把U盘做坏了.将U盘用量产工具修复以后就能做启动盘了.从官网下了Fedora 28的镜像(与CentOS同属RedHat系,尽量与鸟哥一致),用 ...
- Alpha阶段中间产物——GUI Prototype、WBS及PSP
作业地址:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/1224 内容: GUI Prototype 我的书架 我的书架→添加图书 ...
- 《Linux内核与分析》第八周
by 20135130王川东 一.进程切换关键代码switch-to分析 1.进程调度与进程调度时机分析 1)不同类型的进程有不同的调度要求 分类:I/0-bound:频繁的进行I/o 通常会 ...
- c# dataGridView排序
一.对阿拉伯数字进行自定义排序: 简单有效方法: 1.该列的sortmode属性为auto...(一般默认) 2.比如首列序号,添加该列数据的时候直接添加int即可.切忌不要用string. obje ...
- C#高级编程 (第六版) 学习 第七章:委托和事件
第七章 委托和事件 回调(callback)函数是Windows编程的一个重要方面,实际上是方法调用的指针,也称为函数指针. .Net以委托的形式实现了函数指针的概念,.Net的委托是类型安全的. 委 ...
- 小程序获取 openid 和 session_key
<?php //获取openid function getopenid(){//获取用户ID //code为前端通过 wx.login() 方式获取 $code = $_GET["co ...
- ViewPager、Fragment、Matrix综合使用实现Tab滑页效果
原文地址:http://www.cnblogs.com/kross/p/3372987.html 我们实现一个上面是一个可以左右滑动的页面,下面是三个可点击切换的tab按钮,tab按钮上还有一个激活条 ...
- 解决 Package test is missing dependencies for the following libraries: libcrypto.so.1.0.0
根据项目要求需要用到openssl这个库,看了看编译环境幸好本身就集成了该库.但在编译openssl的功能时,碰到缺少类库的错误. Package test is missing dependenci ...
- PHP对象类型转换
其他数据类型转换为对象类型 其他数据类型转换为对象类型,得到的结果是:内置标准类(stdclass)的一个对象! 语法形式为: $obj1 = (object) 其他类型数据: 数组转换为对象:数 ...
- 51nod-1222-最小公倍数计数
题意 给到 \(a,b\) ,求 \[ \sum _{i=a}^b\sum _x\sum _y[x\le y][\text{lcm}(x,y)=i] \] 即最小公倍数在 \([a,b]\) 中的有序 ...