参考博客: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自动切换的更多相关文章

  1. 【python】-- 协程介绍及基本示例、协程遇到IO操作自动切换、协程(gevent)并发爬网页

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

  2. 利用协程爬网页,自动切换io 精典案例:

    首先Python提供的协程库gevent好像并不能知道那些程序使用了io  所以要加一个补丁,mondey,以下同步和异步各爬一次的案例 : , from urllib import requesti ...

  3. flask之分析线程和协程

    flask之分析线程和协程 01 思考:每个请求之间的关系 我们每一个请求进来的时候都开一个进程肯定不合理,那么如果每一个请求进来都是串行的,那么根本实现不了并发,所以我们假定每一个请求进来使用的是线 ...

  4. Flask 之分析线程和协程

    目录 flask之分析线程和协程 01 思考:每个请求之间的关系 02 threading.local 03 通过字典自定义threading.local 04 通过setattr和getattr实现 ...

  5. 网络编程基础--协程--greenlet切换---gevent自动识别 IO ---

    协程: 1 单线程来实现并发---协程: 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程, 即协程是由用户程序自己控制调度的 只 ...

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

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

  7. 并发异步编程之争:协程(asyncio)到底需不需要加锁?(线程/协程安全/挂起/主动切换)Python3

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_208 协程与线程向来焦孟不离,但事实上是,线程更被我们所熟知,在Python编程领域,单核同时间内只能有一个线程运行,这并不是什么 ...

  8. 异步、+回调机制、线程queue、线程Event、协程、单线程实现遇到IO切换

    # from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor # import requests # import o ...

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

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

随机推荐

  1. PHP使用static关键字声明静态属性和静态方法

    PHP使用static关键字声明静态属性和静态方法 在PHP中,通过static关键字修饰的成员属性和成员方法被称为静态属性和静态方法. 静态属性和静态方法不需要在被类实例化的情况下就可以直接使用. ...

  2. 软银集团和共享办公空间公司WeWork在日本成立合资公司

    [TechWeb报道]7月18日消息,据国外媒体报道,软银集团和共享办公空间公司WeWork联合宣布,在日本成立合资公司WeWork Japan. 该合资公司将在日本开设联合办公空间,于明年初在东京设 ...

  3. SAP(ABAP) ABAP内部外部数据转换常用function

    文本相关CONVERSION_EXIT_CUNIT_OUTPUT      将内部单位转为单位文本CONVERSION_EXIT_ISOLA_OUTPUT      根据语言代码取文本CONVERSI ...

  4. 直接抱过来dd大牛的《背包九讲》来做笔记

    P01: 01背包问题 题目 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 基本思路 这是最 ...

  5. ASP.NET MVC5 学习系列之表单和HTML辅助方法

    一.表单 (一)Action和Method特性 Action特性用以告知浏览器信息发往何处,因此,Action特性后面需要包含一个Url地址.这里的Url地址可以是相对的,也可以是绝对的.如下Form ...

  6. CDOJ ABCDE dp(前缀和优化)

    题目链接: http://acm.uestc.edu.cn/#/problem/show/1307 ABCDE Time Limit: 1000/1000MS (Java/Others)Memory ...

  7. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

  8. http://deepdish.io/2015/04/28/creating-lmdb-in-python/

    http://deepdish.io/2015/04/28/creating-lmdb-in-python/

  9. Struts2(三)

    以下内容是基于导入struts2-2.3.32.jar包来讲的 1.全局视图配置 xml标签:<global-results> <result name="error&qu ...

  10. 结对项目——fault,error,failure的程序设计

    一.结对编程内容: 1.不能触发Fault. 2.触发Fault,但是不触发Error. 3.触发Error,但不触发Failure. 二.结对编程人员 1.周宗耀.周浩: 2.结对截图: 三.结对项 ...