我已经研究 asyncio 模块/功能几天了,因为我想将它用于我的应用程序的 IO 绑定部分,并且我认为我现在对它的工作原理有一个合理的理解,或者在至少我认为我已经理解了以下内容;
- 任一时刻,任一线程中只能运行一个异步事件循环。
- 一旦一切都设置好并准备好,就会调用loop.run_forever()或loop.run_until_complete()来运行循环,并且此调用会永久阻塞线程或直到循环完成,即。同步代码不能(或不应该)与同一线程中的事件循环并行运行。
- 如果您需要从事件循环内部运行阻塞/非确定性同步代码,那么您应该在“执行器”内部运行它,它(如果我的理解是正确的)在事件循环内部嵌入一个线程或进程池并运行那里的代码(在它自己的新线程或进程中?)
- python 的开发人员从未打算让异步代码和同步代码成为同一应用程序的一部分,因为我绝对找不到任何参考资料来解释如何最好地实现线程间/同步/异步代码间通信。
- Asyncio 不是为人类编写的。
考虑到上述考虑,我一直在努力思考如何在后台运行我的异步代码,同时在前台执行其他(同步)工作,我也在谷歌上搜索了很多,并发现很多人有相同的类型问题很多,但提出好的解决方案的人并不多,也没有我满意的解决方案。
所以现在我的问题是; Spyder IDE 是如何做到的???
我正在使用 Spyder IDE,并发现 Spyder 运行自己的异步事件循环,不仅如此,您还可以直接在交互式 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 的理解。