Python异步协程快速恢复技巧
时间:2025-10-31 10:33:32 372浏览 收藏
哈喽!大家好,很高兴又见面了,我是golang学习网的一名作者,今天由我给大家带来一篇《Python 异步协程无需等待启动恢复方法》,本文主要会讲到等等知识点,希望大家一起学习进步,也欢迎大家关注、点赞、收藏、转发! 下面就一起来看看吧!

本文旨在解决在 Python 中启动异步协程时遇到的困惑,并提供一种在不阻塞主线程的情况下,类似 JavaScript 的方式立即执行异步任务的方案。文章深入探讨了 `asyncio` 库的特性,并结合 `run_coroutine_threadsafe` 方法展示了如何在独立的事件循环中运行协程,从而实现异步任务的并行执行和状态监控。
在 Python 的异步编程中,一个常见的困惑是如何立即启动一个异步协程,而无需立即 `await` 它。与 JavaScript 等语言不同,Python 的 `async` 函数在调用时并不会立即执行,而是返回一个协程对象。只有通过 `await`、`asyncio.gather` 等方式,协程才会真正开始执行。 这种行为可能导致一些问题,尤其是在需要尽快启动多个协程,并在稍后等待它们完成的情况下。如果使用 `asyncio.gather`,所有协程会在同一时刻启动,导致潜在的性能瓶颈。 为了解决这个问题,我们可以利用 `asyncio.run_coroutine_threadsafe` 函数,在一个独立的线程中运行协程。这允许协程立即启动,而不会阻塞主线程。 **使用 `run_coroutine_threadsafe`** `asyncio.run_coroutine_threadsafe(coro, loop)` 函数接受一个协程对象 `coro` 和一个事件循环 `loop` 作为参数。它将协程提交到指定的事件循环中,并在该循环中运行协程。该函数返回一个 `concurrent.futures.Future` 对象,可以用来获取协程的结果或检查其状态。 以下是一个示例代码,展示了如何使用 `run_coroutine_threadsafe` 函数: ```python import asyncio import time from threading import Thread global_loop = None def thread_for_event_loop(): global global_loop global_loop = asyncio.new_event_loop() asyncio.set_event_loop(global_loop) global_loop.run_forever() t = Thread(target=thread_for_event_loop) t.daemon = True t.start() time.sleep(1) # wait for thread to start old_print = print print = lambda *_: old_print(round(time.perf_counter(), 1), *_) def attempt(future): # doesn't actually do anything, only prints if task is done print(future.done()) async def work(): print("SETUP") await asyncio.sleep(2) print("MIDDLE") await asyncio.sleep(2) print("END") return "Result" async def main(): print("START", int(time.perf_counter())) task = asyncio.run_coroutine_threadsafe(work(), global_loop) attempt(task) attempt(task) print("before first sleep") time.sleep(3) print("after first sleep") attempt(task) attempt(task) print("before second sleep") time.sleep(3) # Block CPU to wait for second sleeping to finish print("after second sleep") attempt(task) attempt(task) print(await asyncio.wrap_future(task)) asyncio.run(main())代码解释:
- 创建事件循环线程: thread_for_event_loop 函数创建一个新的事件循环,并在一个独立的线程中运行它。这确保了协程在后台运行,而不会阻塞主线程。
- attempt 函数: attempt 函数用于检查协程的状态。它接受一个 Future 对象作为参数,并打印协程是否完成。
- work 协程: work 协程模拟一个耗时任务,其中包含多个 await asyncio.sleep() 调用。
- main 协程: main 协程使用 asyncio.run_coroutine_threadsafe 函数将 work 协程提交到事件循环线程中。然后,它使用 attempt 函数检查协程的状态,并使用 time.sleep() 模拟主线程中的其他工作。
- asyncio.wrap_future: 将 concurrent.futures.Future 包装成 asyncio 的 Future,以便使用 await 等待结果。
运行结果:
1.1 START 1 1.1 False 1.1 False 1.1 before first sleep 1.1 SETUP 3.1 MIDDLE 4.1 after first sleep 4.1 False 4.1 False 4.1 before second sleep 5.1 END 7.1 after second sleep 7.1 True 7.1 True 7.1 Result
注意事项:
- asyncio.run_coroutine_threadsafe 函数需要一个事件循环作为参数。如果当前线程没有事件循环,则需要创建一个新的事件循环。
- asyncio.run_coroutine_threadsafe 函数返回一个 concurrent.futures.Future 对象。可以使用 await asyncio.wrap_future(future) 等待 Future 对象完成并获取结果。
- 在多线程环境中使用 asyncio 时,需要注意线程安全问题。确保所有对 asyncio 对象的访问都是线程安全的。
总结:
通过使用 asyncio.run_coroutine_threadsafe 函数,我们可以实现类似 JavaScript 的异步编程模型,即立即启动异步任务,并在稍后等待它们完成。这种方法可以提高程序的性能和响应速度,尤其是在需要同时运行多个异步任务的情况下。
今天带大家了解了的相关知识,希望对你有所帮助;关于文章的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~
相关阅读
更多>
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
最新阅读
更多>
-
296 收藏
-
351 收藏
-
157 收藏
-
485 收藏
-
283 收藏
-
349 收藏
-
291 收藏
-
204 收藏
-
401 收藏
-
227 收藏
-
400 收藏
-
327 收藏
课程推荐
更多>
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习