在 Python 中,async 关键字用于定义异步函数。这类函数允许任务在后台运行,而不会阻塞其他代码的执行。它通常用于处理网络请求、数据库操作或文件 I/O 等场景------在这些场景中,如果采用同步方式等待某个任务完成,整个程序就会被拖慢。
需要注意的是,async 函数本身并不会自动以异步方式运行;它必须配合 await 才能真正实现"暂停"和"恢复"的效果。换句话说,async 定义了函数的"异步能力",而 await 则是触发这种能力的关键。
要使用 async,我们首先需要导入 asyncio 标准库。若想深入了解,可参考官方文档中关于 Python asyncio 的介绍。
下面来看一个简单示例:
python
import asyncio
async def func():
print("Hello!")
await asyncio.sleep(2) # 暂停 2 秒,但不会阻塞整个程序
print("Geeks for Geeks")
asyncio.run(func())
输出结果:
Hello!
(等待 2 秒)
Geeks for Geeks
说明:
- 在 def 前加上 async,就将 func 定义为一个异步函数。
- await asyncio.sleep(2) 会让当前协程暂停 2 秒,但事件循环仍可处理其他任务(虽然本例中没有其他任务)。
基本语法
python
async def function_name():
await some_async_function()
- async def:定义一个异步函数(也称为"协程函数")。
- await:暂停当前协程的执行,直到被等待的异步操作完成。
使用场景与示例
1. 同时运行多个任务
借助 async,我们可以让多个任务并发执行,而无需等一个任务完成后再启动下一个。
python
import asyncio
async def task1():
print("Task 1 started")
await asyncio.sleep(3)
print("Task 1 finished")
async def task2():
print("Task 2 started")
await asyncio.sleep(1)
print("Task 2 finished")
async def main():
await asyncio.gather(task1(), task2()) # 并发运行两个任务
asyncio.run(main())
输出结果:
Task 1 started
Task 2 started
Task 2 finished
Task 1 finished
说明:
- 虽然 task1() 和 task2() 是按顺序调用的,但由于它们都是异步函数,并且通过 asyncio.gather() 并发调度,因此它们实际上是"同时"开始执行的。
- task2() 只需等待 1 秒,所以先完成;task1() 需要 3 秒,后完成。
2. 异步处理 HTTP 请求
在实际开发中,异步常用于发起多个 HTTP 请求。如果使用同步方式,每个请求都会阻塞程序直到完成;而使用异步,则可以同时发送多个请求,显著提升效率。
⚠️ 注意:你需要先安装 aiohttp 库。若未安装,请在终端运行:
pip
pip install aiohttp
python
import aiohttp
import asyncio
async def fetch_data():
async with aiohttp.ClientSession() as session:
async with session.get("https://example.com/") as response:
data = await response.text()
print(data[:100]) # 打印前 100 个字符
asyncio.run(fetch_data())
输出结果(示例):
<!doctype html>
<html>
<head>
<title>Example Domain</title>
<meta charset="utf-8" />
<m
说明:
- aiohttp 是一个支持异步 HTTP 客户端/服务端的第三方库。
- ClientSession() 创建一个可复用的 HTTP 会话。
- session.get() 是一个异步方法,必须用 await 等待其完成。
- response.text() 也是一个异步方法,同样需要 await。
3. 异步文件 I/O
Python 默认的文件操作是同步的,会阻塞程序执行。虽然标准库对原生异步文件 I/O 支持有限,但我们可以通过第三方库 aiofiles 实现真正的异步读写。
⚠️ 注意:需先安装 aiofiles:
pip
pip install aiofiles
python
import asyncio
import aiofiles
async def write_file():
async with aiofiles.open(r"paste_your_file_path_here\file.txt", "w") as f:
await f.write("Hello from Geeks for Geeks!")
async def read_file():
async with aiofiles.open(r"paste_your_file_path_here\file.txt", "r") as f:
content = await f.read()
print(content)
# 先写入,再读取
asyncio.run(write_file())
asyncio.run(read_file())
输出结果:
Hello from Geeks for Geeks!
说明:
- aiofiles.open() 是 aiofiles 提供的异步文件打开方法,用法类似内置的 open(),但支持 await。
- 写入时,如果指定路径下的文件不存在,会自动创建。
- 读取时,如果文件不存在,则会抛出 FileNotFoundError。
- 原文中函数名写为 write() 和 read(),但解释部分却称其为 write_file() 和 read_file(),存在不一致。此处统一修正为更具描述性的名称。
- 原文重复导入了两次 asyncio,已删除冗余导入。
- 重要提示:虽然 aiofiles 在内部通常使用线程池来模拟异步文件 I/O(因为操作系统层面的异步文件 I/O 支持有限),但它仍能避免阻塞事件循环,适合在异步应用中使用。
总结
- async/await 是 Python 实现并发(非并行)的核心机制,特别适合 I/O 密集型任务。
- 异步函数必须通过 await 调用其他异步操作才能发挥价值。
- 使用 asyncio.run() 是运行顶层异步函数的标准方式(自 Python 3.7 起)。
- 对于网络请求,推荐使用 aiohttp;对于文件操作,可使用 aiofiles。
- 异步 ≠ 多线程,它是在单线程内通过事件循环实现任务切换,资源开销更小。