首页 > 解决方案 > Spyder 如何在同一线程的后台运行 asyncio 事件循环(或者是吗?)

问题描述

我已经研究 asyncio 模块/功能几天了,因为我想将它用于我的应用程序的 IO 绑定部分,并且我认为我现在对它的工作原理有一个合理的理解,或者至少我认为我已经理解了以下内容;

  1. 任何时候任何一个线程中只能运行一个 asyncio 事件循环。
  2. 一旦一切都设置好并准备就绪,就会调用 loop.run_forever() 或 loop.run_until_complete() 来运行循环,并且此调用会永久阻塞线程或直到循环完成,即。没有同步代码可以(或应该)与同一线程中的事件循环并行运行。
  3. 如果您需要从事件循环内部运行阻塞/非确定性同步代码,那么您应该在“执行程序”中运行它(如果我的理解是正确的)在事件循环中嵌入一个线程或进程池并运行那里的代码(在它自己的新线程或进程中?)
  4. python 的开发人员从未打算让异步代码和同步代码成为同一应用程序的一部分,因为我绝对找不到任何参考资料来解释如何最好地实现线程间/同步/异步代码间通信。
  5. Asyncio 不是为人类编写的。

考虑到上述考虑,我一直在苦苦思考如何在后台运行我的异步代码,同时在前台做其他(同步)工作,我也在谷歌上搜索了很多,发现很多同类的问题,但没有多少人有好的解决方案,也没有任何我满意的解决方案。

所以现在我的问题是;Spyder IDE是怎么做到的???

我正在使用 Spyder IDE,发现 Spyder 运行自己的 asyncio 事件循环,不仅如此,您还可以直接在交互式 python 控制台中定义和运行异步函数,只需执行以下操作:

In [1]: async def my_printer():
   ...:     print('hello world')
   ...:
In [2]: asyncio.run_coroutine_threadsafe(my_printer(), asyncio.get_event_loop())
hello world

所以我想我自己“我想知道我在 Spyder 终端中键入的代码实际上是在哪个线程中执行的”,所以我尝试了:

In [3]: import threading
In [4]: threading.current_thread()
<_MainThread(MainThread, started 9756)>

..然后当我尝试时,我的困惑变得更大;

In [5]: async def get_thread():
   ...:     return threading.current_thread()
   ...:
In [6]: res = asyncio.run_coroutine_threadsafe(get_thread(), asyncio.get_event_loop())
In [7]: res.result()
<_MainThread(MainThread, started 9756)>

这到底是怎么回事?

我不明白 Spyder 如何在主线程中运行异步事件循环,同时仍然允许我在同一个线程中运行同步代码。我的理解不正确/我是否遗漏了有关 asyncio 工作原理的信息?或者 Spyder 是否在幕后使用了一些邪恶的黑客手段使其发挥作用?

我主要对此感兴趣,因为我希望它可以帮助我理解同步和异步代码如何协同工作,并且因为它可能会加深我对 asyncio 的理解。

标签: pythonpython-asynciospyder

解决方案


推荐阅读