python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > 使用asyncio包实现异步编程

Python使用asyncio包实现异步编程方式

作者:Sun_Sherry

这篇文章主要介绍了Python使用asyncio包实现异步编程方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

1. 异步编程

异步编程是一种编程范式,用于处理程序中需要等待异步操作完成后才能继续执行的情况。

异步编程允许程序在执行耗时的操作时不被阻塞,而是在等待操作完成时继续执行其他任务。

这对于处理诸如文件 I/O、网络请求、定时器等需要等待的操作非常有用。

使用异步编程通常可以带来以下好处:

2 async/await和asyncio包

2.1 异步函数的定义

在Python中实现异步函数的定义需要两个关键字(asyncawait)。

在Python中异步函数的定义需要同时满足以下两个条件:

2.2 事件循环

事件循环(Event Loop)是异步编程中负责管理和调度异步任务执行的机制。

事件循环的工作原理类似于一个持续运行的循环,它在每一轮循环中都会执行以下几个步骤:

2.2 asyncio包

asyncio包python中常用的异步编程框架,这里使用该框架完成一个简单的异步编程案例,具体如下:

import time
import datetime
import asyncio
async def async_read_file():
    print("async读文件开始:",datetime.datetime.fromtimestamp(time.time()))
    await asyncio.sleep(20)
    print("async读文件完成:",datetime.datetime.fromtimestamp(time.time()))

def computer():
    print("普通计算密集型任务:",datetime.datetime.fromtimestamp(time.time()))
    sum=0
    for i in range(1000000):
        if i%250000==0 and i!=0:
            print("普通计算密集型任务正在执行:",datetime.datetime.fromtimestamp(time.time()))
        for j in range(500):
            sum+=i+j-2*j
    print("普通计算密集型任务完成:",datetime.datetime.fromtimestamp(time.time()))

def computer2():
    print("普通CPU密集型任务:",datetime.datetime.fromtimestamp(time.time()))
    sum=0
    for i in range(1000000):
        if i%250000==0 and i!=0:
            print("普通CPU密集型任务正在执行:",datetime.datetime.fromtimestamp(time.time()))
        for j in range(5000):
            sum+=i+j-2*j
    print("普通CPU密集型任务完成:",datetime.datetime.fromtimestamp(time.time()))

async def asy_main():
    task=loop.create_task(async_read_file()) # 创建一个任务,并添加到事件循环,等待执行
    task2=loop.run_in_executor(None,computer)# 将普通函数read_file添加到事件循环中,等待执行
    task3=loop.run_in_executor(None,computer2)# 将普通函数read_file2添加到事件循环中,等待执行
    await task3
    await task2
    await task

loop=asyncio.get_event_loop() # 创建一个事件循环
loop.run_until_complete(asy_main())

其执行结果如下:

普通计算密集型任务: 2024-05-15 18:29:19.702689
普通CPU密集型任务: 2024-05-15 18:29:19.708280
async读文件开始: 2024-05-15 18:29:19.738654
普通计算密集型任务正在执行: 2024-05-15 18:29:21.441072
普通计算密集型任务正在执行: 2024-05-15 18:29:23.192585
普通计算密集型任务正在执行: 2024-05-15 18:29:24.936979
普通计算密集型任务完成: 2024-05-15 18:29:26.712930
普通CPU密集型任务正在执行: 2024-05-15 18:29:32.539679
async读文件完成: 2024-05-15 18:29:39.752731
普通CPU密集型任务正在执行: 2024-05-15 18:29:41.813872
普通CPU密集型任务正在执行: 2024-05-15 18:29:51.103737
普通CPU密集型任务完成: 2024-05-15 18:30:00.433402

从代码运行结果中可以看到,两个计算密集型的任务task2、task3和异步函数task添加到事件循环上之后,在等待异步操作task完成的过程中,CPU并没有闲着,而是在执行task2和task3的任务。

Tips:虽然当下的执行结果中写完成了computer()的计算,后完成了computer2()的计算,但多次执行上述程序的时候也出现了两个函数交替执行的结果。

为了与上述代码形成对比,执行下述代码:

import asyncio
import datetime

async def async_task(name, delay):
    print(f"Task {name} started:",datetime.datetime.now())
    await asyncio.sleep(delay)
    print(f"Task {name} finished:",datetime.datetime.now())

async def main():
    await async_task("A", 2)
    await async_task("B", 1)
    await async_task("C", 3)

asyncio.run(main())

其代码执行结果如下:

Task A started: 2024-05-21 17:45:24.324535
Task A finished: 2024-05-21 17:45:26.326109
Task B started: 2024-05-21 17:45:26.326250
Task B finished: 2024-05-21 17:45:27.327795
Task C started: 2024-05-21 17:45:27.327923
Task C finished: 2024-05-21 17:45:30.329475

从执行结果上可以看到这三个异步操作是顺序执行的,并没有同时执行。

这是因为在执行await后面的异步操作时事件循环中只有一个任务。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文