uTools-Manuals/docs/python/selectors.html
2019-04-21 11:50:48 +08:00

39 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div class="body" role="main"><div class="section" id="module-selectors"><h1><span class="yiyi-st" id="yiyi-10">18.4.<a class="reference internal" href="#module-selectors" title="selectors: High-level I/O multiplexing."><code class="xref py py-mod docutils literal"><span class="pre">selectors</span></code></a> — 高层 I/O 多路复用 </span></h1><div class="versionadded"><p><span class="yiyi-st" id="yiyi-11"><span class="versionmodified">3.4 版新加入。</span></span></p></div><p><span class="yiyi-st" id="yiyi-12"><strong>源码︰</strong><a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/selectors.py">Lib/selectors.py</a></span></p><div class="section" id="introduction"><h2><span class="yiyi-st" id="yiyi-13">18.4.1. </span><span class="yiyi-st" id="yiyi-14">介绍 </span></h2><p><span class="yiyi-st" id="yiyi-15">这个模块允许高层高效的 I/O 多路复用,建立在 <a class="reference internal" href="select.html#module-select" title="select: Wait for I/O completion on multiple streams."><code class="xref py py-mod docutils literal"><span class="pre">选择</span></code></a> 模块原函数基础之上。</span><span class="yiyi-st" id="yiyi-16">鼓励用户使用此模块,除非他们想精确控制系统级别原函数的使用。</span></p><p><span class="yiyi-st" id="yiyi-17">它定义了 <a class="reference internal" href="#selectors.BaseSelector" title="selectors.BaseSelector"><code class="xref py py-class docutils literal"><span class="pre">BaseSelectorr</span></code></a> 抽象基类,以及几种具体的实现 <a class="reference internal" href="#selectors.KqueueSelector" title="selectors.KqueueSelector"><code class="xref py py-class docutils literal"><span class="pre"> KqueueSelectorr</span></code></a> <a class="reference internal" href="#selectors.EpollSelector" title="selectors.EpollSelector"><code class="xref py py-class docutils literal"><span class="pre">EpollSelectorr</span></code></a>...),可用多个文件对象上等待 I/O 准备就绪的通知。</span><span class="yiyi-st" id="yiyi-18">在下文中,"文件对象"指任何有 <code class="xref py py-meth docutils literal"><span class="pre">fileno()</span></code> 方法或原始文件描述符的对象。</span><span class="yiyi-st" id="yiyi-19">请参阅 <a class="reference internal" href="../glossary.html#term-file-object"><span class="xref std std-term">文件对象</span></a></span></p><p><span class="yiyi-st" id="yiyi-20"><a class="reference internal" href="#selectors.DefaultSelector" title="selectors.DefaultSelector"><code class="xref py py-class docutils literal"><span class="pre">DefaultSelector</span></code></a> 是当前平台上可用的最有效实现的别名︰ 这应该是大多数用户的默认选择。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-21">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-22">支持的文件对象的类型取决于平台︰ 在 Windows 上,支持套接字,但不支持管道,而在 Unix 上,两者都受支持 (某些其他类型可能也支持,比如 fifo 或特殊文件设备)。</span></p></div><div class="admonition seealso"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-23">令请参阅</span></p><dl class="last docutils"><dt><span class="yiyi-st" id="yiyi-24"><a class="reference internal" href="select.html#module-select" title="select: Wait for I/O completion on multiple streams."><code class="xref py py-mod docutils literal"><span class="pre">select</span></code></a></span></dt><dd><span class="yiyi-st" id="yiyi-25">低层 I/O 多路复用模块。</span></dd></dl></div></div><div class="section" id="classes"><h2><span class="yiyi-st" id="yiyi-26">18.4.2. </span><span class="yiyi-st" id="yiyi-27"></span></h2><p><span class="yiyi-st" id="yiyi-28">类层次结构︰</span></p><pre><code class="language-python"><span></span><span class="n">BaseSelector</span>
<span class="o">+--</span> <span class="n">SelectSelector</span>
<span class="o">+--</span> <span class="n">PollSelector</span>
<span class="o">+--</span> <span class="n">EpollSelector</span>
<span class="o">+--</span> <span class="n">DevpollSelector</span>
<span class="o">+--</span> <span class="n">KqueueSelector</span>
</code></pre><p><span class="yiyi-st" id="yiyi-29">在下文中,<em>事件</em> 是指那些等待I/O 事件的给定的文件对象的位掩码。</span><span class="yiyi-st" id="yiyi-30">它可以是下面的模块常量的组合︰</span></p><span class="yiyi-st" id="yiyi-108"> <blockquote> <div><table border="1" class="docutils"> <colgroup> <col width="33%"/> <col width="67%"/> </colgroup> <thead valign="bottom"> <tr class="row-odd"><th class="head">Constant</th> <th class="head">Meaning</th> </tr> </thead> <tbody valign="top"> <tr class="row-even"><td><code class="xref py py-const docutils literal"><span class="pre">EVENT_READ</span></code></td> <td>Available for read</td> </tr> <tr class="row-odd"><td><code class="xref py py-const docutils literal"><span class="pre">EVENT_WRITE</span></code></td> <td>Available for write</td> </tr> </tbody> </table> </div></blockquote></span><dl class="class"><dt id="selectors.SelectorKey"><span class="yiyi-st" id="yiyi-31"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">SelectorKey</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-32"><a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 是一个用来将文件对象关联到其底层文件描述符,选定的事件掩码和附加的数据的 <a class="reference internal" href="collections.html#collections.namedtuple" title="collections.namedtuple"><code class="xref py py-class docutils literal"><span class="pre">namedtuple</span></code></a></span><span class="yiyi-st" id="yiyi-33">它由 <a class="reference internal" href="#selectors.BaseSelector" title="selectors.BaseSelector"><code class="xref py py-class docutils literal"><span class="pre">BaseSelector</span></code></a> 的几种方法返回。</span></p><dl class="attribute"><dt id="selectors.SelectorKey.fileobj"><span class="yiyi-st" id="yiyi-34"> <code class="descname">fileobj</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-35">注册的文件对象。</span></p></dd></dl><dl class="attribute"><dt id="selectors.SelectorKey.fd"><span class="yiyi-st" id="yiyi-36"> <code class="descname">fd</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-37">底层的文件描述符。</span></p></dd></dl><dl class="attribute"><dt id="selectors.SelectorKey.events"><span class="yiyi-st" id="yiyi-38"> <code class="descname">events</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-39">该文件对象必须等待的事件。</span></p></dd></dl><dl class="attribute"><dt id="selectors.SelectorKey.data"><span class="yiyi-st" id="yiyi-40"> <code class="descname">data</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-41">可选的与此文件对象相关联的不透明数据︰ 例如,这可以用来存储每个客户端的会话 id。</span></p></dd></dl></dd></dl><dl class="class"><dt id="selectors.BaseSelector"><span class="yiyi-st" id="yiyi-42"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">BaseSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-43"><a class="reference internal" href="#selectors.BaseSelector" title="selectors.BaseSelector"><code class="xref py py-class docutils literal"><span class="pre">BaseSelector</span></code></a> 用来等待多个文件对象的I/O 事件的准备。</span><span class="yiyi-st" id="yiyi-44">它支持文件流注册、 注销和带可选超时值的等待这些流的 I/O 事件的方法。</span><span class="yiyi-st" id="yiyi-45">它是一个抽象的基类,因此不能实例化。</span><span class="yiyi-st" id="yiyi-46">使用 <a class="reference internal" href="#selectors.DefaultSelector" title="selectors.DefaultSelector"><code class="xref py py-class docutils literal"><span class="pre">DefaultSelector</span></code></a>来替代 或者用 <a class="reference internal" href="#selectors.SelectSelector" title="selectors.SelectSelector"><code class="xref py py-class docutils literal"><span class="pre">SelectSelector</span></code></a><a class="reference internal" href="#selectors.KqueueSelector" title="selectors.KqueueSelector"><code class="xref py py-class docutils literal"><span class="pre">KqueueSelector</span></code></a> 等。</span><span class="yiyi-st" id="yiyi-47">如果您想要明确使用一种实现,和您的平台支持它。</span><span class="yiyi-st" id="yiyi-48"><a class="reference internal" href="#selectors.BaseSelector" title="selectors.BaseSelector"><code class="xref py py-class docutils literal"><span class="pre">BaseSelector</span></code></a> 和其具体的实现支持 <a class="reference internal" href="../glossary.html#term-context-manager"><span class="xref std std-term">上下文管理器</span></a> 协议。</span></p><dl class="method"><dt id="selectors.BaseSelector.register"><span class="yiyi-st" id="yiyi-49"> <em class="property">abstractmethod </em><code class="descname">register</code><span class="sig-paren">(</span><em>fileobj</em>, <em>events</em>, <em>data=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-50">注册一个文件对象到选择器来监视它的 I/O 事件。</span></p><p><span class="yiyi-st" id="yiyi-51"><em>fileobj</em> 是要监视的文件对象。</span><span class="yiyi-st" id="yiyi-52">它可能是一个整型文件描述符或有 <code class="docutils literal"><span class="pre">fileno()</span></code> 方法的对象。</span><span class="yiyi-st" id="yiyi-53"><em>events</em> 是要监视的事件的位掩码。</span><span class="yiyi-st" id="yiyi-54"><em>data</em> 是不透明的对象。</span></p><p><span class="yiyi-st" id="yiyi-55">这返回一个新的 <a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例,或者因无效的事件掩码或文件描述符抛出 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a> 错误,或者如果文件对象已注册则抛出 <a class="reference internal" href="exceptions.html#KeyError" title="KeyError"><code class="xref py py-exc docutils literal"><span class="pre">KeyError</span></code></a> 错误。</span></p></dd></dl><dl class="method"><dt id="selectors.BaseSelector.unregister"><span class="yiyi-st" id="yiyi-56"> <em class="property">abstractmethod </em><code class="descname">unregister</code><span class="sig-paren">(</span><em>fileobj</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-57">从选择器注销一个文件对象并移除对它的监视。</span><span class="yiyi-st" id="yiyi-58">文件对象被注销前应先关闭。</span></p><p><span class="yiyi-st" id="yiyi-59"><em>fileobj</em> 必须是先前注册过的文件对象。</span></p><p><span class="yiyi-st" id="yiyi-60">这返回关联的 <a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例,或者如果 <em>fileobj</em>未注册则抛出 <a class="reference internal" href="exceptions.html#KeyError" title="KeyError"><code class="xref py py-exc docutils literal"><span class="pre">KeyError</span></code></a>错误。</span><span class="yiyi-st" id="yiyi-61">如果 <em>fileobj</em> 无效则抛出<a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a>错误(例如,</span><span class="yiyi-st" id="yiyi-62">它没有 <code class="docutils literal"><span class="pre">fileno()</span></code> 方法或其 <code class="docutils literal"><span class="pre">fileno()</span></code> 方法有无效的返回值)。</span></p></dd></dl><dl class="method"><dt id="selectors.BaseSelector.modify"><span class="yiyi-st" id="yiyi-63"> <code class="descname">modify</code><span class="sig-paren">(</span><em>fileobj</em>, <em>events</em>, <em>data=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-64">更改已注册的文件对象的监视事件或附加数据。</span></p><p><span class="yiyi-st" id="yiyi-65">这就相当于先 <code class="xref py py-meth docutils literal"><span class="pre">BaseSelector.unregister(fileobj)()</span></code><code class="xref py py-meth docutils literal"><span class="pre">BaseSelector.register (fileobj,</span> <span class="pre">events,</span> <span class="pre">data)()</span></code>,只是,它可以更有效地执行。</span></p><p><span class="yiyi-st" id="yiyi-66">这返回一个新的 <a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例,或者因无效的事件掩码或文件描述符抛出 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a> 错误,或者如果文件对象已注册则抛出 <a class="reference internal" href="exceptions.html#KeyError" title="KeyError"><code class="xref py py-exc docutils literal"><span class="pre">KeyError</span></code></a> 错误。</span></p></dd></dl><dl class="method"><dt id="selectors.BaseSelector.select"><span class="yiyi-st" id="yiyi-67"> <em class="property">abstractmethod </em><code class="descname">select</code><span class="sig-paren">(</span><em>timeout=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-68">等到一些已注册的文件对象准备好或者超时。</span></p><p><span class="yiyi-st" id="yiyi-69">如果 <code class="docutils literal"><span class="pre">timeout</span> <span class="pre">&gt;</span> <span class="pre">0</span></code>,会指定最长的等待时间,以秒为单位。</span><span class="yiyi-st" id="yiyi-70">如果 <code class="docutils literal"><span class="pre">timeout</span> <span class="pre">&lt; =</span> <span class="pre">0</span></code>,调用不会阻塞并会报告目前准备好的文件对象。</span><span class="yiyi-st" id="yiyi-71">如果 <em>timeout</em><code class="docutils literal"><span class="pre">None</span></code>,调用将会阻塞直到一个监视的文件对象准备好。</span></p><p><span class="yiyi-st" id="yiyi-72">这将返回一个以 <code class="docutils literal"><span class="pre">(key,</span> <span class="pre">events)</span></code> 元组为元素的列表,每一个元祖代表一个准备好的文件对象。</span></p><p><span class="yiyi-st" id="yiyi-73"><em>key</em> 是对应于一个准备好的文件对象的<a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例。</span><span class="yiyi-st" id="yiyi-74"><em>events</em> 是该文件对象上准备好的事件位掩码。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-75">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-76">如果当前进程接收到信号,此方法可以在超时前或任何文件对象准备好前返回:在这种情况下,将返回一个空列表。</span></p></div><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-77"><span class="versionmodified">3.5 版本中的更改︰</span>当被一个信号中断时,如果信号处理程序不抛出异常 (见 <span class="target" id="index-0"></span> <a class="pep reference external" href="https://www.python.org/dev/peps/pep-0475"><strong>PEP 475</strong></a> 原因),现在选择器再次重新计算超时,而不是在超时前返回一个空的事件列表。</span></p></div></dd></dl><dl class="method"><dt id="selectors.BaseSelector.close"><span class="yiyi-st" id="yiyi-78"> <code class="descname">close</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-79">关闭选择器。</span></p><p><span class="yiyi-st" id="yiyi-80">这个必须调用以确保所有底层资源被释放。</span><span class="yiyi-st" id="yiyi-81">一旦选择器被关闭就不能再使用。</span></p></dd></dl><dl class="method"><dt id="selectors.BaseSelector.get_key"><span class="yiyi-st" id="yiyi-82"> <code class="descname">get_key</code><span class="sig-paren">(</span><em>fileobj</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-83">返回一个与已注册的文件对象关联的键值。</span></p><p><span class="yiyi-st" id="yiyi-84">这返回关联此文件对象的 <a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例,或如果文件对象未注册则抛出 <a class="reference internal" href="exceptions.html#KeyError" title="KeyError"><code class="xref py py-exc docutils literal"><span class="pre">KeyError</span></code></a>错误。</span></p></dd></dl><dl class="method"><dt id="selectors.BaseSelector.get_map"><span class="yiyi-st" id="yiyi-85"> <em class="property">abstractmethod </em><code class="descname">get_map</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-86">返回文件对象到选择器键值的映射。</span></p><p><span class="yiyi-st" id="yiyi-87">这将返回一个已注册的文件对象到与其关联的 <a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例的映射的 <a class="reference internal" href="collections.abc.html#collections.abc.Mapping" title="collections.abc.Mapping"><code class="xref py py-class docutils literal"><span class="pre">Mapping</span></code></a> 实例。</span></p></dd></dl></dd></dl><dl class="class"><dt id="selectors.DefaultSelector"><span class="yiyi-st" id="yiyi-88"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">DefaultSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-89">默认选择器类使用在当前平台上可用的最有效的实现。</span><span class="yiyi-st" id="yiyi-90">这应该是大多数用户的默认选择。</span></p></dd></dl><dl class="class"><dt id="selectors.SelectSelector"><span class="yiyi-st" id="yiyi-91"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">SelectSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-92">基于<a class="reference internal" href="select.html#select.select" title="select.select"><code class="xref py py-func docutils literal"><span class="pre">select.select()</span></code></a>的选择器。</span></p></dd></dl><dl class="class"><dt id="selectors.PollSelector"><span class="yiyi-st" id="yiyi-93"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">PollSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-94">基于<a class="reference internal" href="select.html#select.poll" title="select.poll"><code class="xref py py-func docutils literal"><span class="pre">select.poll()</span></code></a>的选择器。</span></p></dd></dl><dl class="class"><dt id="selectors.EpollSelector"><span class="yiyi-st" id="yiyi-95"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">EpollSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-96">基于<a class="reference internal" href="select.html#select.epoll" title="select.epoll"><code class="xref py py-func docutils literal"><span class="pre">select.epoll()</span></code></a>的选择器。</span></p><dl class="method"><dt id="selectors.EpollSelector.fileno"><span class="yiyi-st" id="yiyi-97"> <code class="descname">fileno</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-98">这将返回底层的 <a class="reference internal" href="select.html#select.epoll" title="select.epoll"><code class="xref py py-func docutils literal"><span class="pre">select.epoll()</span></code></a> 对象所使用的文件描述符。</span></p></dd></dl></dd></dl><dl class="class"><dt id="selectors.DevpollSelector"><span class="yiyi-st" id="yiyi-99"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">DevpollSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-100">基于<a class="reference internal" href="select.html#select.devpoll" title="select.devpoll"><code class="xref py py-func docutils literal"><span class="pre">select.devpoll()</span></code></a>的选择器。</span></p><dl class="method"><dt id="selectors.DevpollSelector.fileno"><span class="yiyi-st" id="yiyi-101"> <code class="descname">fileno</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-102">这将返回底层的 <a class="reference internal" href="select.html#select.devpoll" title="select.devpoll"><code class="xref py py-func docutils literal"><span class="pre">select.devpoll()</span></code></a> 对象所使用的文件描述符。</span></p></dd></dl><div class="versionadded"><p><span class="yiyi-st" id="yiyi-103"><span class="versionmodified">3.5版本中新加入。</span></span></p></div></dd></dl><dl class="class"><dt id="selectors.KqueueSelector"><span class="yiyi-st" id="yiyi-104"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">KqueueSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-105">基于<a class="reference internal" href="select.html#select.kqueue" title="select.kqueue"><code class="xref py py-func docutils literal"><span class="pre">select.kqueue()</span></code></a>的选择器。</span></p><dl class="method"><dt id="selectors.KqueueSelector.fileno"><span class="yiyi-st" id="yiyi-106"> <code class="descname">fileno</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-107">这将返回底层的 <a class="reference internal" href="select.html#select.kqueue" title="select.kqueue"><code class="xref py py-func docutils literal"><span class="pre">select.kqueue()</span></code></a> 对象所使用的文件描述符。</span></p></dd></dl></dd></dl></div><div class="section" id="examples"><h2><span class="yiyi-st" id="yiyi-109">18.4.3. </span><span class="yiyi-st" id="yiyi-110">示例 </span></h2><p><span class="yiyi-st" id="yiyi-111">这里是一个简单的回显服务器的实现︰</span></p><pre><code class="language-python"><span></span><span class="kn">import</span> <span class="nn">selectors</span>
<span class="kn">import</span> <span class="nn">socket</span>
<span class="n">sel</span> <span class="o">=</span> <span class="n">selectors</span><span class="o">.</span><span class="n">DefaultSelector</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">accept</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">mask</span><span class="p">):</span>
<span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span> <span class="c1"># Should be ready</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'accepted'</span><span class="p">,</span> <span class="n">conn</span><span class="p">,</span> <span class="s1">'from'</span><span class="p">,</span> <span class="n">addr</span><span class="p">)</span>
<span class="n">conn</span><span class="o">.</span><span class="n">setblocking</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
<span class="n">sel</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="n">selectors</span><span class="o">.</span><span class="n">EVENT_READ</span><span class="p">,</span> <span class="n">read</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">read</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="n">mask</span><span class="p">):</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span> <span class="c1"># Should be ready</span>
<span class="k">if</span> <span class="n">data</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'echoing'</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="s1">'to'</span><span class="p">,</span> <span class="n">conn</span><span class="p">)</span>
<span class="n">conn</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="c1"># Hope it won't block</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'closing'</span><span class="p">,</span> <span class="n">conn</span><span class="p">)</span>
<span class="n">sel</span><span class="o">.</span><span class="n">unregister</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">()</span>
<span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="s1">'localhost'</span><span class="p">,</span> <span class="mi">1234</span><span class="p">))</span>
<span class="n">sock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">setblocking</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
<span class="n">sel</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">selectors</span><span class="o">.</span><span class="n">EVENT_READ</span><span class="p">,</span> <span class="n">accept</span><span class="p">)</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="n">events</span> <span class="o">=</span> <span class="n">sel</span><span class="o">.</span><span class="n">select</span><span class="p">()</span>
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">mask</span> <span class="ow">in</span> <span class="n">events</span><span class="p">:</span>
<span class="n">callback</span> <span class="o">=</span> <span class="n">key</span><span class="o">.</span><span class="n">data</span>
<span class="n">callback</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">fileobj</span><span class="p">,</span> <span class="n">mask</span><span class="p">)</span>
</code></pre></div></div></div>