async 是 Python 异步编程的基石关键字,它和 await 一起构成了现代 Python 异步 I/O 的核心语法。


一、async 的核心作用

async 关键字用于定义“协程函数”(coroutine function)——一种可以暂停和恢复执行的特殊函数。

类比理解:

  • 普通函数:像一条直线,从头跑到尾,中间不能停。
  • 协程函数(async def):像一条有“检查点”的跑道,跑到 await 处可以暂停,让别人先跑,等轮到自己再继续。

二、async 怎么使用?——基本语法

基本形式:

async def function_name(parameters):
    # 函数体
    await some_async_operation()  # 可选,但通常会有
    return result

示例 1:最简单的协程函数

async def greet(name):
    return f"Hello, {name}!"

# 调用它
coro = greet("Alice")
print(type(coro))  # <class 'coroutine'> —— 返回一个协程对象,不是结果!

⚠️ 注意:调用 greet("Alice") 不会立即执行函数体,而是返回一个协程对象(coroutine object)。


三、async def vs 普通 def 的关键区别

全屏复制

特性def(普通函数)async def(协程函数)
调用返回值直接返回结果返回 协程对象(需 await 或事件循环执行)
内部能否用 await❌ 不能✅ 可以
执行方式立即执行需由事件循环调度执行
是否可暂停❌ 不可✅ 在 await 处可暂停

四、如何真正“运行”一个协程函数?

仅仅调用 async def 函数不会执行它!你需要以下方式之一:

方式 1:在另一个协程中 await 它(推荐)

async def main():
    result = await greet("Bob")  # ✅ 真正执行并获取结果
    print(result)  # Hello, Bob!

方式 2:用 asyncio.run() 启动(顶层入口)

import asyncio

# 在脚本顶层
result = asyncio.run(greet("Charlie"))
print(result)  # Hello, Charlie!

方式 3:提交给事件循环(高级)

loop = asyncio.new_event_loop()
task = loop.create_task(greet("David"))
loop.run_until_complete(task)
print(task.result())  # Hello, David!

✅ 最佳实践

  • 应用入口用 asyncio.run(main())
  • 内部协程互相调用用 await

五、async 的常见使用场景

场景 1:异步 I/O 操作(网络、文件、数据库)

import aiohttp

async def fetch(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

场景 2:并发执行多个任务

async def main():
    urls = ["https://a.com", "https://b.com"]
    tasks = [fetch(url) for url in urls]
    results = await asyncio.gather(*tasks)  # 并发获取

场景 3:异步上下文管理器

async def read_file(path):
    async with aiofiles.open(path, 'r') as f:  # 异步文件操作
        return await f.read()

场景 4:异步生成器(async def + yield

async def async_range(n):
    for i in range(n):
        await asyncio.sleep(0.1)
        yield i

async def main():
    async for x in async_range(3):  # 异步迭代
        print(x)

六、重要规则与限制

✅ 规则 1:await 只能在 async def 中使用

def bad(): 
    await something()  # ❌ SyntaxError!

✅ 规则 2:async def 函数必须被正确执行

# 错误:创建了协程但没执行
greet("Eve")  # 警告:coroutine 'greet' was never awaited

✅ 规则 3:不要在 async def 中调用阻塞函数

async def bad_io():
    time.sleep(2)  # ❌ 阻塞整个事件循环!
    
async def good_io():
    await asyncio.sleep(2)  # ✅ 非阻塞

七、async 修饰的其他对象(进阶)

除了函数,async 还可用于:

1. 异步上下文管理器__aenter____aexit__

class AsyncResource:
    async def __aenter__(self):
        print("Acquiring resource")
        return self
        
    async def __aexit__(self, *args):
        print("Releasing resource")

async def main():
    async with AsyncResource() as res:  # ✅
        pass

2. 异步迭代器__aiter____anext__

class AsyncCounter:
    def __init__(self, n):
        self.n = n
        self.i = 0
        
    def __aiter__(self):
        return self
        
    async def __anext__(self):
        if self.i < self.n:
            await asyncio.sleep(0.1)
            self.i += 1
            return self.i
        raise StopAsyncIteration

async def main():
    async for x in AsyncCounter(3):  # ✅
        print(x)

八、常见误区澄清

❌ 误区 1:“加了 async 就变快了”

✅ 正确:async 本身不加速,只有配合异步 I/O 和并发才能提升吞吐量。

❌ 误区 2:“async def 函数会自动并发执行”

✅ 正确:必须用 create_task() 或 gather() 显式并发,否则仍是顺序执行。

❌ 误区 3:“async/await 是多线程”

✅ 正确:默认是单线程事件循环,通过协作式多任务实现并发。


九、总结:async 的本质

全屏复制

问题答案
async 作用?定义可暂停/恢复的协程函数
如何使用?async def func(): ...
调用后发生什么?返回协程对象,需 await 或事件循环执行
必须搭配什么?通常搭配 await 使用
适用场景?I/O 密集型任务(网络、文件、DB)

💡 终极口诀
async 定义暂停点,await 触发执行流;
单线程高并发,I/O 等待不再愁。”

掌握 async,你就掌握了 Python 异步编程的第一把钥匙!

更多推荐