Python 协程以及事件循环的问题,怎么知道 IO 读取结束了呢?

2018-06-23 02:59:52 +08:00
 867810107

最近在学习 python 的 asyncio 库,但是有很多的疑问无法得到解答。 在《流畅的 python 》中有一个例子,出租车的离散事件仿真,它是用一个主循环调度几个协程,利用优先级队列来调度,但是每一次的运行时间(利用这个运行时间来模拟 IO 需要的时间)是在主循环中计算的。
关于上面那个例子可以参照这里: https://segmentfault.com/a/1190000009798067
那么我的第一个问题是: 我用类似上面的思想来理解 asyncio,也就是有一个队列,主循环会不停地从队列里取出下一个要做的事。当遇到了 IO,我们怎么知道 IO 的时间呢?不知道 IO 的时间我们怎么去排定它的运行时间并把它放进队列里呢?

还是说这样理解,IO 是系统调用,理解为不在我们的线程里运行了,当系统 IO 结束了它会自动把运行完的事件加到队列中?这样我们就从队列里知道 IO 完了又开心地回到刚才进行 IO 操作的那个协程里去了?
...可是我们是怎么控制系统调用把完成时的事件放到队列中呢...还必须是与 python 兼容的格式...而且系统调用我们应该是无法控制的啊...
还是说其实得到系统调用返回的结果其实很简单...有人能写一下代码示意一下吗?因为我一直不知道系统完成 IO 的通知应该通知到我们代码的哪一行里面。

第二个问题: 由此我引发了对其他异步的思考...比如 JavaScript 是单线程的,那么它其实就是一个事件循环是吗?会不断地从队列里取出下一次要做的事情。比如鼠标点击就会把点击的事件加到队列中,然后 js 从中拿到事件,调用对应的回调函数。那么也就是说 JavaScript 的单线程也只能处理“响应的部分”,而鼠标点击这个事件的捕捉是系统做的。虽然 JavaScript 的运行是单线程的,但是是需要多个线程的配合才能完成复杂的交互操作是吗?

最后一个问题: 如果我上面说的和 python 事件循环的原理类似,那么假设我要怎么把系统的通知放到队列中?比如我现在读一个文件,文件读取完毕的通知我怎么把它包装成符合 python 的形式放到队列中?而且是异步,这时我们在执行别的代码,通知会跑到哪里去呢?比如我要把它组装成一个 namedtuple event(name='read_down'),然后把它放到我们已经定义了的队列中呢?有大神能帮忙写一下吗...
只学了两个月,很多理解不到位,希望大神指教。

2277 次点击
所在节点    Python
1 条回复
wwqgtxx
2018-06-23 03:25:11 +08:00
可异步的系统调用肯定会有一个句柄可以通过类似于 wait 的调用来等待其完成,而这一类的句柄可以通过一种类似于 select 的调用批量监听,系统会在其中一个句柄有状态更新的时候返回

其实学 asyncio 最好的办法就是直接读 asyncio 的源代码,其中大部分模块都是 python 写的,所以并不难看懂

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/465178

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX