掌握 Python 异步编程与 asyncio 库 —— 提升高并发编程效率

掌握 Python 异步编程与 asyncio 库 —— 提升高并发编程效率

Python 中的异步编程,尤其是 asyncio 库,是实现高性能应用的强大工具。它可以让代码非阻塞地运行多个任务,非常适合高并发的场景,比如处理大量 I/O 操作或 Web 请求。下面,我们将从基础概念出发,一步步深入,最终带你写出流畅高效的异步代码。


1. 为什么选择异步编程?

异步编程可以显著提升性能,特别是在处理大量 I/O 操作时。传统的同步编程要求每个操作依次完成,意味着在等待一个文件读写或网络响应时,程序会停在那里浪费时间。而异步编程可以在等待时接着处理其他任务,充分利用 CPU,提升整体效率。

比如:假设我们有一个应用需要处理成百上千个 Web 请求,异步编程可以让应用程序一边等待网络响应,一边处理其他请求,而不用卡在那里傻等。这样就可以大大提高系统的吞吐量和响应速度。


2. 同步 vs 异步编程:概念和对比

  • 同步编程:传统上,Python 是同步执行的,也就是按顺序运行每一行代码。如果有个地方需要等待,比如等待网络请求返回,那么后面的代码会一直卡住,直到请求结束。

  • 异步编程:异步编程允许程序在等待的过程中继续运行其他代码。你可以把它想象成一个「会 multitask 的人」,只要有个地方需要等,他会暂时放下这部分,接着做其他事。这个特性在需要并发处理的场景中非常高效。


3. Python 异步编程基础:事件循环、协程和任务

事件循环(Event Loop)是什么?

事件循环是 asyncio 的核心。简单来说,它是一个调度器,负责管理和调度所有的异步任务。所有的协程、任务、I/O 操作等都会提交给事件循环,由它来决定什么先执行,什么后执行。

在 Python 中,你可以使用 asyncio.run() 来启动一个事件循环,并运行你的异步代码。

协程(Coroutine)是什么?

协程是异步代码的基本单元。它有点像普通的函数,但不同的是,它的执行可以暂停(使用 await 关键字),然后在需要的时候继续运行。这样,程序可以切换到其他任务上,不用一直等着协程执行完毕。

在 Python 中,协程通过 async def 定义,比如:

import asyncio

async def my_coroutine():
    print("这是一个协程")
    await asyncio.sleep(1)  # 模拟I/O等待
    print("协程执行完毕")

任务(Task)是什么?

任务是协程的一种包装形式,它是事件循环中的实际执行单元。通过 asyncio.create_task(),可以把协程包装成任务,并提交到事件循环中。

任务和协程的区别是:协程只是一个潜在的任务,只有被事件循环执行时才会变成真正的任务。


4. asyncio 的基本用法

我们来看看 asyncio 中几个核心的用法。

启动事件循环并运行协程

import asyncio

async def main():
    print("启动主协程")
    await asyncio.sleep(2)
    print("主协程完成")

# 使用 asyncio.run() 启动事件循环并运行主协程
asyncio.run(main())

上面的代码创建了一个事件循环,运行了 main() 协程。await asyncio.sleep(2) 用来模拟一个耗时操作(比如网络请求),程序会等待 2 秒,然后打印完成消息。

创建并发任务

asyncio.create_task() 是让多个任务并发执行的关键。例如,我们同时启动两个任务,看看它们如何并行执行:

import asyncio

async def download_data(name, delay):
    print(f"{
     
     name} 开始下载数据")
    await asyncio.sleep(delay)
    print(f"{
     
     name} 数据下载完成")

async def main():
    # 创建两个并发任务
    task1 = asyncio.create_task(download_data(
### Python `asyncio` 异步编程教程 #### 三、定义协程函数 在Python中,可以通过`async def`语句来定义一个协程函数。当调用这样的函数时,它并不会立即执行而是返回一个可以被等待完成的协程对象。 ```python async def my_coroutine(): await asyncio.sleep(1) print("Coroutine executed") ``` 此段代码展示了如何创建简单的协程函数[^4]。 #### 四、使用事件循环运行单个协程 为了启动并运行协程直到其结束,在最基础的情况下可以直接利用`asyncio.run()`方法传递要执行的任务给默认事件循环处理: ```python import asyncio async def say_after(delay, what): await asyncio.sleep(delay) print(what) async def main(): print(f"started at {time.strftime('%X')}") await say_after(1, 'hello') await say_after(2, 'world') print(f"finished at {time.strftime('%X')}") # This line runs the event loop and waits until completion of all coroutines. asyncio.run(main()) ``` 这段程序会依次打印时间戳以及'hello'和'world'[^1]。 #### 五、并发执行多个协程 如果希望同时发起几个独立的操作而不需要等到前一个完成后才开始下一个,则应该考虑采用更高级的方式如通过`gather()`收集所有待办事项作为一组任务一起提交给事件循环去调度它们之间的执行顺序: ```python import asyncio async def factorial(name, number): f = 1 for i in range(2, number + 1): print(f"Task {name}: Compute factorial({i})...") await asyncio.sleep(1) f *= i print(f"Task {name}: factorial({number}) = {f}") async def main(): # Schedule three calls *concurrently*: await asyncio.gather( factorial("A", 2), factorial("B", 3), factorial("C", 4), ) await main() ``` 上述例子说明了怎样让不同名称的任务并行计算阶乘值[^3]。 #### 六、设置超时期限 有时候可能需要限制某个操作的最大允许持续时间;这时就可以借助于`timeout()`辅助工具来做这件事儿——一旦超过指定的时间就会抛出异常终止该过程,并且还可以尝试调整已设定好的时限长度而不必重建整个环境配置. ```python import asyncio async def coroutine1(): await asyncio.sleep(5) print('coroutine1 finished') async def main(): try: async with asyncio.timeout(1): await coroutine1() except TimeoutError as e: print(e) asyncio.run(main()) ``` 这里展示了一个带有超时机制的例子,其中任何未能及时完成的工作都会被捕获为特定类型的错误实例[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值