1. 引言
asyncio 是 Python3.4 引入的一个标准库,用于编写异步代码。它提供了一种协程(coroutine)的方式,可以在单线程下实现多任务,避免了多线程代码中常见的锁、线程切换等问题,从而提高了程序的执行效率。在本文中,我们将深入探讨 asyncio 模块的使用和原理。
2. 协程与异步
2.1 协程
协程是一种轻量级的线程,也称为用户态线程。它可以在一个线程中实现多任务并发处理,而不需要进行线程上下文的切换。在 Python 中,使用 async def 定义一个协程函数,同时使用 await 关键字来挂起当前协程的执行,等待另一个协程的执行完成后再继续执行。
2.2 异步
在计算机中,异步通常指的是不等待某个操作的完成,而是在操作完成之前返回,继续执行其他操作,以提高程序的响应速度。在 asyncio 中,我们使用异步的方式来执行协程,通常使用 async/await 关键字来实现。
3. asyncio 的基本用法
3.1 定义协程函数
在 asyncio 中,我们使用 async def 关键字来定义协程函数。协程函数的执行顺序和普通函数不同,它需要使用 await 关键字等待另一个协程函数的执行结果,才能继续执行下去。
import asyncio
async def hello():
print("Hello, world!")
await hello()
上述代码定义了一个协程函数 hello,并使用 await 关键字来等待它的执行结果。在 Python 3.7 及以上版本中,可以直接使用 asyncio.run() 函数来执行一个协程函数。
import asyncio
async def hello():
print("Hello, world!")
asyncio.run(hello())
3.2 运行事件循环
在 asyncio 中,事件循环是非常重要的一个概念,它用于管理协程的执行顺序。我们可以使用 asyncio.get_event_loop() 函数来获取默认的事件循环,使用 loop.run_until_complete() 函数来运行协程,直到协程全部执行完成才停止。
import asyncio
async def hello():
print("Hello, world!")
loop = asyncio.get_event_loop()
loop.run_until_complete(hello())
4. asyncio 的高级用法
4.1 asyncio.sleep()
asyncio.sleep() 函数用于等待一段时间后再继续执行协程。在等待期间,事件循环会挂起当前协程的执行,并开始执行其他协程。
import asyncio
async def hello():
print("Start")
await asyncio.sleep(1)
print("End")
loop = asyncio.get_event_loop()
loop.run_until_complete(hello())
4.2 asyncio.create_task()
asyncio.create_task() 函数用于创建一个协程任务,将其添加到事件循环中。相比于直接使用 run_until_complete() 函数执行协程,这种方式更加灵活,可以同时运行多个协程。
import asyncio
async def foo():
print("Foo")
async def bar():
print("Bar")
loop = asyncio.get_event_loop()
task1 = loop.create_task(foo())
task2 = loop.create_task(bar())
loop.run_until_complete(asyncio.wait([task1, task2]))
4.3 asyncio.wait()
asyncio.wait() 函数用于等待多个协程任务全部执行完毕。
import asyncio
async def foo():
print("Foo")
async def bar():
print("Bar")
loop = asyncio.get_event_loop()
tasks = [loop.create_task(foo()), loop.create_task(bar())]
loop.run_until_complete(asyncio.wait(tasks))
4.4 asyncio.gather()
asyncio.gather() 函数用于并行执行多个协程任务,并将它们的执行结果集合在一起返回。
import asyncio
async def my_sum():
total = 0
for i in range(10):
total += i
await asyncio.sleep(0.1)
return total
async def my_product():
product = 1
for i in range(1, 6):
product *= i
await asyncio.sleep(0.2)
return product
loop = asyncio.get_event_loop()
results = loop.run_until_complete(asyncio.gather(my_sum(), my_product()))
print(results)
4.5 asyncio.Lock()
asyncio.Lock() 函数用于创建一个锁对象,来控制多个协程之间的互斥访问。在一个协程获取了锁对象之后,其他协程就不能再获取该锁对象,直到该协程释放锁。
import asyncio
async def task(lock):
print("start")
async with lock:
print("get lock")
await asyncio.sleep(0.5)
print("end")
loop = asyncio.get_event_loop()
lock = asyncio.Lock()
tasks = [task(lock) for i in range(10)]
loop.run_until_complete(asyncio.wait(tasks))
5. 总结
本文介绍了 asyncio 模块的基本用法和高级用法,包括协程函数的定义、事件循环的运行、休眠、任务创建、任务等待、任务并行执行和锁对象等内容。了解这些内容对于编写高效的异步代码非常重要。希望本文可以帮助大家更好地理解和使用 asyncio 模块。