陌小兮 發表於 2019-5-23 15:41:00

协程系列之Event Loops

<h1 id="event-loops">Event Loops</h1>
<h3 id="事件循环">事件循环</h3>
<p><strong>事件</strong>是由程序的一部分在特定条件下发出的消息,<strong>循环</strong>是在某种条件下完成并执行某个程序直到它完成的构造,因此,<strong>事件循环</strong>是一个循环,它允许用户订阅事件传输并注册处理程序/回调。 它使程序能够以异步方式运行。事件循环将它收到的所有事件委托给各自的回调,大多数回调模式的实现都有一个主要缺点,他们以引入大量嵌套的方式规定编程风格。因此,为了表示程序的某些部分彼此依赖,我们使用排序,然而,在依赖于异步结果的情况下,出现了以下模式:</p>
<ul>
<li>嵌套回调,以便内部回调可以访问外部回调的结果(闭包)</li>
<li>使用充当未来结果代理的对象(所谓的 Future 或 Promise )</li>
<li>协程,它是在事件循环中运行的可挂起函数</li>
</ul>
<h4 id="nesting-callback嵌套回调">Nesting Callback(嵌套回调)</h4>
<p>嵌套回调的经验法则是,如果需要等待回调的结果,则必须将代码嵌入到相应的回调中。你很快就会陷入臭名昭着的回调地狱般的局面。回调地狱是回调嵌套的深度,这使得程序的推理和改进成为一种噩梦。</p>
<h4 id="futurespromises">Futures/Promises</h4>
<p>Futures/Promises 是封装异步调用的结果和错误处理的对象。它们最终会提供 APIs 来查询results/exceptions 的当前状态,以及注册回调来处理 results/exceptions 的方法。由于它们封装了异步调用的未来上下文并需要嵌套,因此生成的程序似乎以更自上而下的方式编写。(.then那种形式)</p>
<h4 id="coroutines">Coroutines</h4>
<p>你可以简单把协程理解为可以中断的函数。暂停意味着我们可以在函数任何位置暂停协程。这意味着它一定有某种原子单位组成。这就是我们所说的 tick,也就是我们所测量的 tick。tick 是事件循环的时间单位, 它包含在事件循环的一个迭代步骤中发生的所有操作</p>
<p>协程实际上可以做得更多:它们可以暂停自己并等待另一个协同程序的结果。<br>
waiiting 的所有逻辑由事件循环协调,因为它知道相应的协程状态</p>
<h3 id="asyncio中事件循环的生命周期">Asyncio中事件循环的生命周期</h3>
<p>asyncio中的事件循环有四种状态:<br>
1.Idle<br>
2.Running<br>
3.Stopped<br>
4.Closed<br>
您可以通过四种事件循环方法与事件循环的生命周期进行交互,这些方法可以分为启动,停止和关闭方法。 它们构成了事件循环生命周期接口,所有 asyncio /第三方事件循环都需要提供兼容性。</p>
<p>1.run_forever<br>
2.run_until_complete</p>
<p>调用 run_forever 方法时没有参数,而 run_until_complete 方法需要传入一个协程函数作为参数。要停止,我们可以使用 stop 方法;要关闭,我们使用 close 方法。</p>
<h4 id="the-idle-state空闲状态">The Idle State(空闲状态)</h4>
<p>空闲状态是创建循环后所处的状态。在此状态下不消耗任何协程或者回调函数。在这个状态下 <strong>loop.is_running</strong> 返回 False。</p>
<h4 id="the-running-state运行状态">The Running State(运行状态)</h4>
<p>运行状态是在调用 <strong>loop.run_forever</strong> 或 <strong>loop.run_until_complete</strong> 之后循环所处的状态。在这个状态下 <strong>loop.is_running</strong> 返回 True。<br>
这些方法之间的区别在于,在 <strong>loop.run_until_complete</strong> 的情况下,<strong>loop.run_until_complete</strong> 会将协程被包装在 <strong>asyncio.Future</strong><br>
中。回调在 asyncio.Future 对象上注册为处理程序,该对象在完全消耗协程后运行loop.stop 方法。</p>
<h4 id="the-stopped-state停止状态">The Stopped State(停止状态)</h4>
<p>停止状态是调用stop命令后循环所处的状态。调用stop方法后,调用<strong>is_running</strong>方法不会返回False,首先消耗所有挂起的回调。只有在它们被消耗之后,循环才会进入空闲状态。</p>
<h4 id="the-closed-state关闭状态">The Closed State(关闭状态)</h4>
<p>循环通过调用close方法进入关闭状态。只有当循环不处于运行状态时,才能调用它。</p>
<h3 id="事件循环的基本类">事件循环的基本类</h3>
<p>在Python 3中默认提供两种事件循环。<br>
抽象事件循环类由asyncio.events和asyncio.base_events模块提供。<br>
AbstractEventLoop和BaseEventLoop表示事件循环实现的两个潜在类。</p>
<h4 id="abstracteventloop">AbstractEventLoop</h4>
<p>AbstractEventLoop类定义了原生asyncio中事件循环的接口。<br>
接口方法可以大致分为以下几个部分</p>
<ul>
<li>生命周期方法(运行、停止、查询状态和关闭循环)</li>
<li>调度方法</li>
<li>回调</li>
<li>协程</li>
<li>创建Future对象</li>
<li>线程相关的方法</li>
<li>IO操作相关的方法</li>
<li>低层级API(socket, pipe, and reader/writer APIs)</li>
<li>高层级APIs(server, pipe, and subprocess-related methods)</li>
<li>信号方法</li>
<li>调试标志管理方法</li>
</ul>
<p>该应用编程接口是稳定的,在手动事件循环实现的情况下可以被子类化</p>
<h4 id="baseeventloop">BaseEventLoop</h4>
<p>尽管基于更高级别的组件,但不应使用BaseEventLoop类来创建手动循环实现,因为它的API不稳定。 但它可以作为一个如何实现接口的指南。<br>
它的BaseEventLoop._run_once方法在循环的每个tick上调用,因此包含一次迭代所需的所有操作。这将调用所有当前准备好的回调,I/O轮询,调度生成的回调,然后调度call_later回调,如果您计划自己实现事件循环,则需要提供与其类似的方法,函数的名称和主体只是实现细节。</p>
<h3 id="事件循环是特定于操作系统的吗">事件循环是特定于操作系统的吗?</h3>
<p>是的,事件循环是特定于操作系统的 这可能会影响API可用性和事件循环的速度。 例如,add_signal_handler和remove_signal_handler是仅限UNIX的循环API。<br>
除了缺少相应的本机绑定之外,操作系统特性背后的原因之一是大多数环路都是基于selectors模块实现的。selectors是基于select模块的提高的高级I/O多路复用接口。<br>
selectors模块建立在Select, poll, devpoll, epoll, or kqueue之上,具体取决于底层操作系统。selectors模块中的模块负责设置默认选择器,而默认选择器又被异步模块使用。</p>
<pre><code>if 'KqueueSelector' in globals():
   DefaultSelector = KqueueSelector
elif 'EpollSelector' in globals():
   DefaultSelector = EpollSelector
elif 'DevpollSelector' in globals():
   DefaultSelector = DevpollSelector
elif 'PollSelector' in globals():
   DefaultSelector = PollSelector
else:
DefaultSelector = SelectSelector
</code></pre>
<p>注意在Windows中还有一个基于I/o完成端口或短IoCP的ProactorEventLoop类实现<br>
IOCP的官方文件将它们描述为“在多处理器系统上处理多个异步输入输出请求的有效线程模型”。例如,如果需要使用asyncio子进程API,可以在Windows上使用ProactorEventLoop。<br>
后续,会不断完善。<br>
更多精彩内容请关注公众号:python学习开发</p><br><br>
来源:https://www.cnblogs.com/c-x-a/p/10912286.html
頁: [1]
查看完整版本: 协程系列之Event Loops