IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Pytho协程之asyncio -> 正文阅读

[Python知识库]Pytho协程之asyncio

前言

这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题

于是乎,我自己开发了一款面试宝典,希望能帮到大家,也希望有更多的Python新人真正加入从事到这个行业里,让python火不只是停留在广告上。

微信小程序搜索:Python面试宝典

或可关注原创个人博客:https://lienze.tech

也可关注微信公众号,不定时发送各类有趣猎奇的技术文章:Python编程学习

AsyncIO

说到实现协程,就不得不说asyncio模块

asyncio是Python3.4之后的协程模块,使用async/await语法,是目前多种Python协程异步框架首选的异步实现方法

协程可以(摘自官方):

  • 等待一个future结束,这个可以暂时理解为一个即将/正在执行过程的协程方法
  • 等待另一个协程(产生一个结果,或引发一个异常)
  • 产生一个结果给正在等它的协程
  • 引发一个异常给正在等它的协程

基本概念

要理解asyncio的原理, 需要理解如下几个概念: 协程、事件循环、future/task

其中协程就是用户自己定义的任务,事件循环负责监听事件和回调,future/task则主要负责管理回调,以及驱动协程


事件循环所做的全部工作就是等待事件发生,然后再将每个事件与我们已明确与所述事件类型匹配的函数进行匹配

EventLoop

EventLoop事件循环负责同时对多个事件进行监听,当监听到事件时,就调用对应的回调函数,进而驱动不同的任务

比如接下来要对协程进行调用的asyncio.run,其本质就是创建一个事件循环,然后一直运行事件循环,直到加入这个循环中的所有任务结束为止

Task

是Python中与事件循环进行交互的一种主要方式,创建Task,意思就是把协程封装成Task实例,并追踪协程的运行/完成状态,用于未来获取协程的结果

Task的核心作用是为了创建多个可以并发执行的任务


通过asyncio.create_task()创建Task,其次调用实现并发

async def func(i):
    print('start-%s' % i)
    await asyncio.sleep(1)
    print('over-%s' % i)

async def main():
    t1 = asyncio.create_task(func(1))
    t2 = asyncio.create_task(func(2))

    await t1
    await t2
asyncio.run(main())

""" 输出
start-1
start-2
over-1
over-2
"""

Future

Future,又称未来对象、期程对象,其本质上是一个容器,用于接受异步执行的结果,是线程不安全的

而之前的Task属于继承自Future,Future 相较于 Task 属于更底层的概念,在开发过程中用到的并不多


Furture 对象内部封装了一个_state,这个_state 维护着四种状态:PendingRunningDoneCancelled

如果变成Done完成,就不再等待,而是往后执行,事件循环凭借着四种状态(阻塞、运行态、完成、取消)对Future协程对象进行调度

awaitable

如果一个对象可以在await语句中使用,那么它就是可等待(awaitable)对象;许多asyncio API都被设计为接受可等待对象

可等待对象有三种主要类型: 协程TaskFuture.

编写协程

asyncio通过asyncawait进行协程方法的编写以及调用

协程的定义,需要使用async def语句

import asyncio

async def function():
    print('这是一个协程方法')
    return 1

async def main():
    await function()
    return 0

验证某个方法是否为协程,可以通过asyncio.iscoroutinefunction(main)

>>> asyncio.iscoroutinefunction(main)
>>> True

调用协程

直接对协程进行函数调用,不会让其真正的调用,而是返回一个coroutine对象,即协程,这一点与生成器函数类似

可以通过如下方法进行协成任务的执行调用


asyncio.run: 这个方法经常用来执行最高层级的类似上面的main这样的起点协程方法

import asyncio

...
asyncio.run(main())

await: 在另一个已经运行的协程中用await等待它,await语句必须在async方法中使用

import asyncio

...
async def main():
    await function() # 这里
    return 0

并发调用协程

awaitable asyncio.gather(*aws, loop=None, return_exceptions=False)

并发运行aws序列中的协程tasksfuture,如果return_exceptionsTrue,异常会和成功的结果一样处理,并聚合至结果列表


首先设计一个函数用以输出当前时间

import datetime

def current_time():
    #  获取当前时间
    return datetime.datetime.now().strftime("%H:%M:%S")

接着是一个用以批量创建的协程方法,非常简单,只是用来输出运行、执行结束、及返回

在执行过程,还添加了一个休眠时间进行阻塞

async def func(sleep_time):
    print(f"[{current_time()}] 执行函数 {func.__name__}-{sleep_time}")
    await asyncio.sleep(sleep_time)
    print(f"[{current_time()}] 执行完毕 {func.__name__}-{sleep_time} ")
    return f"函数 {func.__name__}-{sleep_time}"

如果是一个个函数非并发执行结束,那么打印效果,可能类似如下

[11:15:32] 执行异步函数 func-0
[11:15:32] 函数 func-0 执行完毕
[11:15:32] 执行异步函数 func-1
[11:15:33] 函数 func-1 执行完毕
...

创建一定数量的func对应的协程

async def run():
    task_list = []
    for i in range(5):
        task = asyncio.create_task(func(i))
        task_list.append(task)

    done = await asyncio.gather(*task_list) # 并发调用
    print(done) # 输出结果

执行

def main():
    asyncio.run(run())

if __name__ == '__main__':
    main()

并发的执行后,结果是这样的

[11:30:54] 执行函数 func-0
[11:30:54] 执行函数 func-1
[11:30:54] 执行函数 func-2
[11:30:54] 执行函数 func-3
[11:30:54] 执行函数 func-4
[11:30:54] 执行完毕 func-0 
[11:30:55] 执行完毕 func-1 
[11:30:56] 执行完毕 func-2 
[11:30:57] 执行完毕 func-3 
[11:30:58] 执行完毕 func-4 
['函数 func-0', '函数 func-1', '函数 func-2', '函数 func-3', '函数 func-4']

等待并发

coroutine asyncio.wait(aws, *, loop=None, timeout=None, return_when=ALL_COMPLETED)

asyncio.wait同样可以并发执行aws序列中的可等待对象,当满足return_when参数指定条件时,将会返回

timeout: [float/int],则它将被用于控制返回之前等待的最长秒数

return_when: 返回的条件

  • FIRST_COMPLETED: 函数将在任意可等待对象结束或取消时返回
  • FIRST_EXCEPTION: 函数将在任意可等待对象因引发异常而结束时返回
  • ALL_COMPLETED: 函数将在所有可等待对象结束或取消时返回

返回结果为两个集合,分别代表着执行结束阻塞


还是上一个示例所用到的一些基本函数

并发的函数

import asyncio

async def func(sleep_time):
    print(f"[{current_time()}] 执行函数 {func.__name__}-{sleep_time}")
    await asyncio.sleep(sleep_time)
    print(f"[{current_time()}] 执行完毕 {func.__name__}-{sleep_time} ")

async def run():
    task_list = []
    for i in range(2):
        task = asyncio.create_task(func(i))
        task_list.append(task)

    done, pending = await asyncio.wait(task_list, return_when=FIRST_COMPLETED)
    print(done)
    print(pending)

def main():
    asyncio.run(run())

if __name__ == '__main__':
    main()

当第一个任务执行结束之后,由于FIRST_COMPLETED的设置,已经可以拿到donepending结果

最终的输出如下

[12:01:57] 执行函数 func-0
[12:01:57] 执行函数 func-1
[12:01:57] 执行完毕 func-0 
{<Task finished name='Task-2' coro=<func() done, defined at /Users/zege/Desktop/1.py:11> result='函数 func-0'>}
{<Task pending name='Task-3' coro=<func() running at /Users/zege/Desktop/1.py:13> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x10b1fc670>()]>>}
  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-10-22 10:53:42  更:2021-10-22 10:55:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 21:35:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码