脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|shell|

服务器之家 - 脚本之家 - Python - Python 异步之在 Asyncio中如何运行阻塞任务详解

Python 异步之在 Asyncio中如何运行阻塞任务详解

2023-03-22 16:47冷冻工厂 Python

这篇文章主要为大家介绍了Python 异步之在 Asyncio 中运行阻塞任务示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

阻塞任务是阻止当前线程继续进行的任务。

如果在 asyncio 程序中执行阻塞任务,它会停止整个事件循环,从而阻止任何其他协程继续进行。

我们可以通过 asyncio.to_thread() 和 loop.run_in_executor() 函数在 asyncio 程序中异步运行阻塞调用。

1. 阻塞任务

asyncio的重点是异步编程和非阻塞IO。然而,我们经常需要在 asyncio 应用程序中执行阻塞函数调用。

这可能有很多原因,例如:

  • 执行 CPU 密集型任务,例如计算某事。
  • 执行阻塞 IO 绑定任务,如从文件读取或写入。
  • 调用不支持 asyncio 的第三方库。

直接在 asyncio 程序中进行阻塞调用将导致事件循环在执行阻塞调用时停止。它不允许其他协程在后台运行。

我们如何在 asyncio 程序中异步执行阻塞调用?

2. 如何运行阻塞任务

asyncio 模块提供了两种在 asyncio 程序中执行阻塞调用的方法。

第一种是使用 asyncio.to_thread() 函数。这是在高级 API 中,供应用程序开发人员使用。

asyncio.to_thread() 函数采用要执行的函数名和任何参数。

该函数在单独的线程中执行。它返回一个可以作为独立任务等待或安排的协程。

?
1
2
3
...
# execute a function in a separate thread
await asyncio.to_thread(task)

在返回的协程有机会在事件循环中运行之前,任务不会开始执行。asyncio.to_thread() 函数在后台创建一个 ThreadPoolExecutor 来执行阻塞调用。因此,asyncio.to_thread() 函数仅适用于 IO 绑定任务。

另一种方法是使用 loop.run_in_executor() 函数。

这是在低级异步 API 中,首先需要访问事件循环,例如通过 asyncio.get_running_loop() 函数。

loop.run_in_executor() 函数接受一个执行器和一个要执行的函数。

如果没有为执行器提供,则使用默认执行器,即 ThreadPoolExecutor。

loop.run_in_executor() 函数返回一个可等待对象,如果需要可以等待它。任务将立即开始执行,因此返回的可等待对象不需要等待或安排阻塞调用开始执行。

?
1
2
3
4
5
...
# get the event loop
loop = asyncio.get_running_loop()
# execute a function in a separate thread
await loop.run_in_executor(None, task)

或者,可以创建一个执行器并将其传递给 loop.run_in_executor() 函数,该函数将在执行器中执行异步调用。

在这种情况下,调用者必须管理执行器,一旦调用者完成它就将其关闭。

?
1
2
3
4
5
6
7
8
...
# create a process pool
with ProcessPoolExecutor as exe:
    # get the event loop
    loop = asyncio.get_running_loop()
    # execute a function in a separate thread
    await loop.run_in_executor(exe, task)
    # process pool is shutdown automatically...

这两种方法允许阻塞调用作为异步任务在 asyncio 程序中执行。

现在我们知道如何在 asyncio 程序中执行阻塞调用,让我们看一些有效的例子。

3. 实例

我们可以探索如何使用 asyncio.to_thread() 在 asyncio 程序中执行阻塞 IO 绑定调用。

在这个例子中,我们将定义一个函数来阻塞调用者几秒钟。然后,我们将使用 asyncio.to_thread() 函数在 asyncio 的线程池中异步执行此函数。

这将使呼叫者腾出时间继续其他活动。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# SuperFastPython.com
# example of running a blocking io-bound task in asyncio
import asyncio
import time
# a blocking io-bound task
def blocking_task():
    # report a message
    print('Task starting')
    # block for a while
    time.sleep(2)
    # report a message
    print('Task done')
# main coroutine
async def main():
    # report a message
    print('Main running the blocking task')
    # create a coroutine for  the blocking task
    coro = asyncio.to_thread(blocking_task)
    # schedule the task
    task = asyncio.create_task(coro)
    # report a message
    print('Main doing other things')
    # allow the scheduled task to start
    await asyncio.sleep(0)
    # await the task
    await task
# run the asyncio program
asyncio.run(main())

运行示例首先创建 main() 协程并将其作为 asyncio 程序的入口点运行。main() 协程运行并报告一条消息。然后它发出对线程池的阻塞函数调用的调用。然后将协程包装在任务中并独立执行。

main() 协程可以自由地继续其他活动。在这种情况下,它会休眠片刻以允许计划任务开始执行。这使得目标函数可以在后台下发给 ThreadPoolExecutor 并开始运行。

然后 main() 协程挂起并等待任务完成。阻塞函数报告一条消息,休眠 2 秒,然后报告最后一条消息。

这突出了我们如何在一个单独的线程中与 asyncio 程序异步执行阻塞 IO 绑定任务。

?
1
2
3
4
Main running the blocking task
Main doing other things
Task starting
Task done

以上就是Python 异步: 在 Asyncio 中运行阻塞任务的详细内容,更多关于Python 异步Asyncio阻塞运行的资料请关注服务器之家其它相关文章!

原文链接:https://juejin.cn/post/7205903144173748282

延伸 · 阅读

精彩推荐
  • Pythonpython中logging库的使用总结

    python中logging库的使用总结

    Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用,下面这篇文章主要给大家介绍了关于python中logging库使用的一些知识总结,文...

    郭西西4732020-12-12
  • PythonPython 实现将某一列设置为str类型

    Python 实现将某一列设置为str类型

    这篇文章主要介绍了Python 实现将某一列设置为str类型,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    Ethan Lee5842020-07-14
  • PythonPyTorch实现手写数字的识别入门小白教程

    PyTorch实现手写数字的识别入门小白教程

    这篇文章主要介绍了python实现手写数字识别,非常适合小白入门学习,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参...

    B.Bz7052023-02-23
  • Pythonpython 利用for循环 保存多个图像或者文件的实例

    python 利用for循环 保存多个图像或者文件的实例

    今天小编就为大家分享一篇python 利用for循环 保存多个图像或者文件的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    深度学习就不了中国人4782021-04-17
  • PythonPython二进制串转换为通用字符串的方法

    Python二进制串转换为通用字符串的方法

    今天小编就为大家分享一篇Python二进制串转换为通用字符串的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    张土豆15052021-03-20
  • Pythonpython关键字传递参数实例分析

    python关键字传递参数实例分析

    在本篇文章里小编给大家整理的是一篇关于python关键字传递参数实例分析内容,有需要的朋友们可以学习参考下。...

    小妮浅浅6192021-11-29
  • Python教你使用Python提取视频中的美女图片

    教你使用Python提取视频中的美女图片

    这篇文章主要介绍了教你使用Python提取视频中的美女图片,使用 Python 写一个逐帧无损保存视频画面的小脚本,大概分为三个步骤,详细过程跟随小编一起看...

    蚂蚁ailing10382022-11-30
  • Python通过数据库向Django模型添加字段的示例

    通过数据库向Django模型添加字段的示例

    这篇文章主要介绍了通过数据库向Django模型添加字段的示例,Django是人气最高的Python web开发框架,需要的朋友可以参考下...

    Python教程网4322020-07-25