前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python中的异步编程:深入理解和使用asyncio库

Python中的异步编程:深入理解和使用asyncio库

原创
作者头像
蚂蚁蚂蚁
发布2024-04-10 13:40:58
5.7K0100
代码可运行
发布2024-04-10 13:40:58
举报
文章被收录于专栏:技术分享
运行总次数:100
代码可运行

asyncio 是 Python 的一个内置库,它的主要用途是编写单线程并发代码,主要通过协程实现。这个库在 Python 3.4 版本中引入,作为 Python 的异步 I/O 框架,提供了基于事件循环的并发模型。

在 Python 3.4 之前,Python 的并发主要依赖于多线程和多进程,但这两种方式都有其局限性。多线程受到全局解释器锁(GIL)的限制,无法充分利用多核 CPU。而多进程虽然可以利用多核 CPU,但进程间的通信复杂,且开销大。因此,Python 社区开始寻找新的并发解决方案,最终在 Python 3.4 中引入了 asyncio

asyncio 的主要特点是事件循环和协程。事件循环是 asyncio 的核心,可以理解为一个无限循环,我们可以把一些函数(通过 async 定义的函数,称为协程)注册到事件循环上,当满足事件发生的条件时,调用相应的协程函数。

协程是 asyncio 的另一个重要概念。协程是一种比线程更轻量级的存在,协程的调度完全由用户控制,协程之间的切换不涉及系统调用,开销极小。Python 中的协程并不是线程安全的,它们应该运行在同一个线程中。如果想要在多线程中使用协程,需要为每个线程创建一个事件循环。

Python 3.5 版本对 asyncio 进行了进一步的改进,引入了新的关键字 asyncawait,使得协程的定义和调用更加简洁明了。

Python 3.7 版本对 asyncio 进行了一些优化和改进,增加了如 asyncio.run() 等新的 API,使得运行和管理协程更加方便。

总的来说,asyncio 的引入使得 Python 在处理 I/O 密集型任务时,能够以更加高效的方式进行并发编程,极大地提高了 Python 的性能。

在 Python 中使用 asyncio 库,首先需要确保你的 Python 环境中已经安装了这个库。如果你的 Python 环境是 3.4 或更高版本,那么 asyncio 库应该已经默认安装。你可以通过以下命令来检查 asyncio 是否已经安装:

代码语言:python
代码运行次数:10
复制
import asyncio

如果这个命令没有报错,那么说明 asyncio 已经安装。如果报错,那么你需要通过 pip 来安装 asyncio 库。在命令行中输入以下命令:

代码语言:bash
复制
pip install asyncio

如果你的 Python 环境是 3.3 或更低版本,那么你需要安装 Trollius 库,这是一个 asyncio 的替代品。你可以通过以下命令来安装 Trollius 库:

代码语言:bash
复制
pip install trollius

安装完成后,你就可以在 Python 代码中导入 asyncio 库,并使用它的功能了。例如,你可以定义一个异步函数,然后使用 asyncio.run() 来运行这个函数。你也可以使用 asyncio.create_task() 来创建一个任务,然后使用 asyncio.run() 来运行这个任务。

此外,你还可以使用 asyncio 的事件循环功能。事件循环是 asyncio 的核心部分,它可以管理和调度多个异步任务。你可以使用 asyncio.get_event_loop() 来获取当前的事件循环,然后使用事件循环的 run_until_complete() 方法来运行一个任务,或者使用事件循环的 run_forever() 方法来持续运行事件循环。

总的来说,asyncio 库提供了一种简单有效的方式来处理异步 I/O 操作,它可以帮助你编写出更高效的 Python 代码。

asyncio 的使用

在 Python 中,我们可以使用 asyncio 库来实现异步 I/O 操作。这个库使用了协程(coroutine)的概念,使得我们可以在单线程环境中实现并发操作。

首先,我们需要定义一个异步函数,这个函数需要使用 async 关键字进行定义。例如,我们定义一个简单的异步函数 do_something,这个函数会计算一系列数字的立方并打印出结果:

代码语言:python
代码运行次数:56
复制
import asyncio

async def do_something():
    l = []
    for i in range(10000):
        l.append(i ** 3)
    print(len(l))
    print(\"finish.\")

异步函数需要使用 await 关键字进行调用。如果我们直接调用异步函数,它只会返回一个 coroutine 对象,并不会执行函数。我们需要使用 asyncio.run 来执行异步函数,或者在其他异步函数中使用 await 关键字进行调用:

代码语言:python
代码运行次数:15
复制
# 只会返回一个 coroutine 对象,并不会执行函数
def main():
    do_something()

# 要用 run 来执行
asyncio.run(do_something())

# 或者在别的异步函数中调用
async def main():
    await do_something() # 异步函数通过 await 来调用,await 只能放在 async 函数内

asyncio.run(main())

我们也可以通过旧式的 API 运行异步函数:

代码语言:python
代码运行次数:1
复制
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

如果我们需要同时执行多个异步函数,我们需要将异步函数定义为 task。我们可以使用 asyncio.create_task 来创建 task,然后使用 await 关键字来启动所有的 task:

代码语言:python
代码运行次数:5
复制
async def main():
    print(f\"started at {time.strftime('%X')}\")
    task1 = asyncio.create_task(do_something_cost_time(\"WashClothes\", 2))
    task2 = asyncio.create_task(do_something_cost_time(\"WatchTV\", 5))
    task3 = asyncio.create_task(do_something_cost_time(\"FeedBaby\", 3))
    await task1 
    await task2
    await task3
    print(f\"finished at {time.strftime('%X')}\") 
asyncio.run(main())

我们也可以使用 asyncio.gather 的方式同时定义并执行 tasks:

代码语言:python
代码运行次数:4
复制
async def main():
    await asyncio.gather(
        do_something_cost_time(\"WashClothes\", 2),
        do_something_cost_time(\"WatchTV\", 5),
        do_something_cost_time(\"FeedBaby\", 3),
    )
    
asyncio.run(main())

或者通过旧式的 API 运行:

代码语言:python
代码运行次数:1
复制
loop = asyncio.get_event_loop()
tasks = [
    do_something_cost_time(\"WashClothes\", 2),
    do_something_cost_time(\"WatchTV\", 5),
    do_something_cost_time(\"FeedBaby\", 3),
]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

asyncio 中,事件循环(Event Loop)是非常重要的一个概念。事件循环的核心是一个 Queue,在一个循环中不断 pop 下一个 ready 的 callback 来执行。我们可以使用以下方式来创建和操作事件循环:

代码语言:python
代码运行次数:8
复制
# create and access a new asyncio event loop
loop = asyncio.new_event_loop()

# access the running event loop
loop = asyncio.get_running_loop()

# to execute a task (blocking)
loop.run_until_complete(asyncio.sleep(2))

# schedule a task (non blocking)
task = loop.create_task(asyncio.sleep(2))

# close the event loop
loop.close()

# stop the event loop
loop.stop()

# run forever until stopped
loop.run_forever()

# check loop status
loop.is_running()
loop.is_closed()

我们也可以在 Process/Thread Executor 中运行事件循环:

代码语言:python
代码运行次数:0
复制
# create an executor
with ThreadPoolExecutor() as exe:
    # execute a function in event loop using executor
    loop.run_in_executor(exe, task)

以上就是 Python 中 asyncio 库的基本使用方法,希望对你有所帮助。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • asyncio 的使用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档