「Python 基础」异步 I/O 编程

2023-11-04

I/O 密集型应用程序大大提升系统多任务处理能力;

异步 I/O 模型

一个消息循环,主线程在消息循环中不断重复 读取消息-处理消息

# 获取线程池
loop = get_event_loop()
while True:
    # 接收事件消息
    event = loop.get_event()
    # 处理事件消息
    process_event(event)

当遇到 I/O 操作,代码只会发出 I/O 请求,不等待 I/O 结果,当本轮消息结束,下轮接收消息收到 I/O 完成时,处理 I/O 结果;

1. 协程

调度策略由程序员自己编写,在用户态完成创建、切换、销毁,通过协作而非抢占,对内核来说不可见的 用户空间线程

协程的本质是控制流的主动让出(yield)和恢复(resume)机制

  • 子程序,又叫函数,在所有语言都是层级调用,通过栈实现,一个线程就是执行一个子程序,子程序调用总是一个入口,一次返回,调用顺序明确;

  • Coroutine,Python 对协程的支持通过 generator 实现,执行时内部可中断,转而执行别的子程序,再适时返回接着执行(类似 CPU 中断);

协程没有线程切换(抢占式)的开销,且不存在变量冲突,不需要线程锁,效率比多线程高;

1. 生产者-消费者模型(协程版)

def consumer():
    r = ''
    while True:
        # 2. 通过 yield 回传 r 给 send 调用
        # 4. 接收 send 的消息 n
        n = yield r
        if not n:
            return
        print(f'[CONSUMER] Consuming {n}...')
        r = '200 OK'


def produce(c):
    # 1. 启动生成器
    c.send(None)
    n = 0
    while n < 5:
        n += 1
        print(f'[PRODUCER] Producing {n}...')
        # 3. 发送消息 n 返回给 yield
        # 5. 接收 yield 的结果 r
        r = c.send(n)
        print(f'[PRODUCER] Consumer return: {r}')
    # 6. 关闭生成器
    c.close()


# 消费者 - 生成器对象
c = consumer()
produce(c)

2. asyncio

Python 3.4 引入标准库,提供了完善的异步 I/O 支持;

asyncio的编程模型是一个消息循环,首先需要从asyncio获取一个EventLoop的引用,然后把执行的协程扔到EventLoop中执行,从而实现异步 I/O;

import asyncio


# @aysncio.coroutine 把 generator 标记成 coroutine
@asyncio.coroutine
def wget(host):
    print('wget %s...' % host)
    connect = asyncio.open_connection(host, 80)
    # yield from 调用 connect 生成器,并接受 connect 的调用结果
    # 主线程并未等待 connect 调用,而是执行 EventLoop 中其他 coroutine
    reader, writer = yield from connect
    header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host
    writer.write(header.encode('utf-8'))
    yield from writer.drain()
    while True:
        line = yield from reader.readline()
        if line == b'\r\n':
            break
        print('%s header > %s' % (host, line.decode('utf-8').rstrip()))
    # Ignore the body, close the socket
    writer.close()


loop = asyncio.get_event_loop()
tasks = [
    wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']
]
# 把 coroutine 扔到 EventLoop 中执行
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

异步操作在coroutine中通过yield from完成;

3. async/await

Python 3.5 引入的针对 coroutine 的新语法;

  • async,替换 @asyncio.coroutine
  • await,替换 yield from

4. aiohttp

  • asyncio,实现了TCPUDPSSL等协议;
  • aiohttp,基于asyncio实现了HTTP框架;

1. 安装

$ pip install aiohttp

2. 示例

import asyncio
from aiohttp import web


async def index(request):
    await asyncio.sleep(1)
    return web.Response(body=b'<h1>Index</h1>')


async def hello(request):
    await asyncio.sleep(1)
    text = '<h1>hello, %s!</h1>' % request.match_info['name']
    return web.Response(body=text.encode('utf-8'))


async def init(loop):
    app = web.Application(loop=loop)
    app.router.add_route('GET', '/', index)
    app.router.add_route('GET', '/hello/{name}', hello)
    # 利用 asyncio 创建 TCP 服务
    srv = await loop.create_server(app.make_handler(), '', 8000)
    print('server started at http://localhost:8000...')
    return srv


loop = asyncio.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()

PS:欢迎各路道友阅读评论,感谢道友点赞关注收藏

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

「Python 基础」异步 I/O 编程 的相关文章

随机推荐

  • ArcFace: Additive Angular Margin Loss for Deep Face Recognition - 人脸识别

    Paper name ArcFace Additive Angular Margin Loss for Deep Face Recognition Paper Reading Note URL https arxiv org pdf 180
  • cartographer之pose_extrapolator

    pose extrapolator实现了订阅imu odom scan的匹配结果进行位姿的推断 我们先分析一下它的类 几个重要的外部接口 就是public的方法 Returns the time of the last added pose
  • Kotlin使用泛型搭建一个MVP最简单实例

    一 Kot对泛型能有很好的支持 下面的例子 是基于泛型搭建的一个Mvp 感兴趣的话 可以自己debug调试一下 import com sun xml internal rngom parse host Base import java la
  • python+scapy实现扫描工具(扫描主机、端口)

    python scapy实现扫描工具 扫描主机 端口 需要下载的库 扫描工具功能 ARP扫描 ICMP扫描 SYN扫描 FIN扫描 XMAS扫描 NULL扫描 主函数 需要下载的库 可以直接通过pip下载 pip install scapy
  • 【自动驾驶】如何利用深度学习搭建一个最简单的无人驾驶系统

    新智驾按 本文为新智驾独家专栏 作者系佐思产研研究总监周彦武 新智驾经授权发布 国内最牛的无人驾驶厂家的运算平台是这样的 一个英特尔至强 E5 的 CPU 拥有 12 内核 30MB 的二级缓存 运算能力为 400GOPS s 功率消耗为
  • 【深入理解HTTP协议】破冰篇

    前言 本文将会引入HTTP的发展史 相关概念 相关协议 网络分层模型 域名 并搭建HTTP实验环境 参考课程为极客时间罗建锋老师的 透视HTTP协议 讲得很棒 强推 文章目录 1 HTTP协议的发展史 2 HTTP是什么 2 1 协议 2
  • flink-1.13.6提交sql到远程集群终于成功了

    java 1 8 flink 1 13 6 bin scala 2 11 hive 1 1 1 hadoop 2 6 0 cdh5 16 2 通过纯SQL的流模式提交到远程flink集群执行 中间遇到不少问题 现在终于能跑通了 附码云地址
  • Pysyft学习笔记一:dome思路

    Pysyft是一个比较适合学习FL学习小白的开源框架 相比与FATE的高封装性 Pysyft提供了更高的自由度 虽然FATE确实加密算法等等的效果做的非常的好 但是我在Ubuntu下面捣鼓了两天 下载了Mysql Redis等等的一堆东西
  • 设计模式状态模式uml_UML的完整形式是什么?

    设计模式状态模式uml UML 统一建模语言 UML Unified Modeling Language UML is an abbreviation of Unified Modeling Language In the field of
  • 【Mac】Mac安装telnet

    1 美图 2 安装 Homebrew 安装 Homebrew 3 安装 base lcc lcc github brew install telnet Updating Homebrew gt Downloading https homeb
  • linux tr命令用法详解

    tr命令用法详解 转自 https www cnblogs com bingguoguo articles 9188703 html tr命令可以对来自标准输入的字符进行替换 压缩和删除 它可以将一组字符变成另一组字符 经常用来编写优美的单
  • 系统架构演变历史及集群、分布式、微服务、SOA的概念区别

    文章目录 1 系统架构演变历史 1 单一应用架构 ORM 2 垂直应用架构 MVC 3 面向服务框架 SOA 4 微服务架构 1 微服务的特点 2 微服务主要解决的问题与场景 3 微服务的缺点 2 集群和分布式 微服务和soa概念和区别理解
  • 创业有哪些忠告?创业赚钱有哪些思维需要掌握?

    1 做买卖 要接到钱再干活儿 除非是你是在做自个的事 并且你确定将来会出现大收益 2 别做回款长的买卖 它对人的本性的考验太大 大部分人们在钱上的阻碍是挺大的 很多钱你是收不回家的 3 没想搞清楚运营模式 就不必自主创业 不然你将公司的铁架
  • 限制<textarea>文本框的字数长度以及设置右下角动态的字数显示

    平时无论在移动端还是PC端都会经常用到文本框 最常碰到的就是要对文本框里面的字数进行限制还有相对应的把剩余可输入的字数显示在右下角 要实现它并不是很难 直接上代码套用一下就ok了 HTML 因为我这里只用到了一小块地方 所以就直接把文本框C
  • 泛型是什么,为什么要用泛型

    泛型 泛型概述及优势 泛型 是JDK5 中引入的特性 可以在编译阶段约束操作的数据类型 并进行检查 泛型只能支持引用数据类型 集合体系的全部接口和实现类都是支持泛型的使用的 好处 统一数据类型 把运行时期的问题提前到了编译期间 避免了强制类
  • TensorFlow在MNIST中的应用-Softmax回归分类

    参考 TensorFlow技术解析与实战 http wiki jikexueyuan com project tensorflow zh tutorials mnist beginners html http www jianshu com
  • 7-2 一元多项式的乘法与加法运算 JAVA_MAP方案

    7 2 一元多项式的乘法与加法运算 30 分 题目要求 设计函数分别求两个一元多项式的乘积与和 输入格式 输入分2行 每行分别先给出多项式非零项的个数 再以指数递降方式输入一个多项式非零项系数和指数 绝对值均为不超过1000的整数 数字间以
  • PCB layout 注意事项

    过孔方面的注意事项 放置过孔时 放置过孔时 2个过孔之间的能走过一根信号线 注意美观横平竖直 过孔与焊盘的间距 PCB layout 时过孔与焊盘的间距 最好在6mil 1 524mm 以上 因为过孔一般不开阻焊 离焊盘太近会导致过孔露铜
  • BigDecimal中divide方法详解

    1 首先说一下用法 BigDecimal中的divide主要就是用来做除法的运算 其中有这么一个方法 public BigDecimal divide BigDecimal divisor int scale int roundingMod
  • 「Python 基础」异步 I/O 编程

    I O 密集型应用程序大大提升系统多任务处理能力 异步 I O 模型 一个消息循环 主线程在消息循环中不断重复 读取消息 处理消息 获取线程池 loop get event loop while True 接收事件消息 event loop