当前位置:   article > 正文

Python的协程异步IO(asyncio)详解_python asyncio_asyncio python

asyncio python

协程和用户态线程非常接近,用户态线程之间的切换不需要陷入内核,但部分操作系统中用户态线程的切换需要内核态线程的辅助。

协程是编程语言(或者 lib)提供的特性(协程之间的切换方式与过程可以由编程人员确定),是用户态操作。协程适用于 IO 密集型的任务。常见提供原生协程支持的语言有:c++20、golang、python 等,其他语言以库的形式提供协程功能,比如 C++20 之前腾讯的 fiber 和 libco 等等。

1.2 分类

协程有两种,一种无栈协程,python中以 asyncio 为代表, 一种有栈协程,python 中 以 gevent 为代表,本文主要讲解 asyncio 线程。

有栈线程 无栈线程 备注
例子: lua thread python gevent C# yield return C# async\await python asyncio
是否拥有单独的上下文: 上下文包括寄存器、栈帧
局部变量保存位置: 无栈协程的局部变量保存在堆上,比如generator的数据成员。
优点: 1. 每个协程有单独的上下文,可以在任意的嵌套函数中任何地方挂起此协程。 2. 不需要编译器做语法支持,通过汇编指令即可实现 1. 不需要为每个协程保存单独的上下文,内存占用低。 2. 切换成本低,性能更高。
缺点: 1. 需要提前分配一定大小的堆内存保存每个协程上下文,所以会出现内存浪费或者栈溢出。 2. 上下文拷贝和切换成本高,性能低于无栈协程。 1. 需要编译器提供语义支持,比如C# yield return语法糖。 2. 只能在这个生成器内挂起此协程,无法在嵌套函数中挂起此协程。 3. 关键字有一定传染性,异步代码必须都有对应的关键字。作为对比,有栈协程只需要做对应的函数调用。 无栈协程无法在嵌套函数中挂起此协程,有栈协程由于是通过保存和切换上下文包括寄存器和执行栈实现,可以在协程函数的嵌套函数内部yield这个协程并唤醒。

二、python的asyncio协程详解

2.1 介绍

asyncio 是用来编写并发代码的库,使用 async/await 语法。

asyncio 被用作多个提供高性能 Python 异步框架的基础,包括网络和网站服务,数据库连接库,分布式任务队列等等。

asyncio 往往是构建 IO 密集型和高层级 结构化 网络代码的最佳选择。

asyncio 提供一组高层级 API 用于:

  • 并发地运行 Python 协程 并对其执行过程实现完全控制;
  • 执行网络 IO 和 IPC;
  • 控制子进程;
  • 通过队列实现分布式任务;
  • 同步并发代码;
  • 创建和管理事件循环,以提供异步 API 用于 网络化, 运行 子进程,处理 OS 信号 等等;
  • 使用 transports 实现高效率协议;
  • 通过 async/await 语法桥接基于回调的库和代码。
2.2 asyncio 协程的使用(用的python3.8的语法)

asyncio 函数的源代码地址:https://github.com/python/cpython/tree/3.8/Lib/asyncio

1)协程通过 async/await 语法进行声明,是编写 asyncio 应用的推荐方式。

asyncio.run() 函数用来运行最高层级的入口点 “main()” 函数。

asyncio.sleep(delay, result=None, *, loop=None) 函数用来阻塞指定的秒数。

# coding=utf8

import sys
import asyncio

async def main():
     print('hello')
     await asyncio.sleep(1)
     print('world')

asyncio.run(main())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
2)事件循环函数(包括循环的创建、运行和停止)

asyncio.get_running_loop() 函数返回当前 OS 线程中正在运行的事件循环。
asyncio.get_event_loop() 函数获取当前事件循环。
asyncio.set_event_loop(loop) 函数将 loop 设置为当前 OS 线程的当前事件循环。
asyncio.new_event_loop() 函数创建一个新的事件循环。
loop.run_until_complete(future) 函数运行直到 future (Future 的实例) 被完成。
loop.run_forever() 函数运行事件循环直到 stop() 被调用。
loop.stop() 函数停止事件循环。
loop.is_running() 函数返回 True 如果事件循环当前正在运行。
loop.is_closed() 函数如果事件循环已经被关闭,返回 True 。
loop.close() 函数关闭事件循环。
loop.create_future() 函数创建一个附加到事件循环中的 asyncio.Future 对象。
loop.create_task(coro, *, name=None) 函数安排一个 协程 的执行。返回一个 Task 对象。
loop.set_task_factory(factory) 函数设置一个 task 工厂 , 被用于 loop.create_task() 。
loop.get_task_factory() 函数返回一个任务工厂,或者如果是使用默认值则返回 None。

示例1:

# coding=utf8

import sys
import asyncio

async def fun1():
    await asyncio.sleep(1)
    print('协程1')

asy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号