1. Stefan Scherfke
  2. pyzmq-article

Commits

Stefan Scherfke  committed ead3fb4

Files for part 2.

  • Participants
  • Parent commits 6ede85a
  • Branches default

Comments (0)

Files changed (9)

File article.html

-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.8.1: http://docutils.sourceforge.net/" />
-<title>Designing and Testing PyZMQ Applications – Part 1</title>
-<style type="text/css">
-
-/*
-:Author: David Goodger (goodger@python.org)
-:Id: $Id: html4css1.css 7056 2011-06-17 10:50:48Z milde $
-:Copyright: This stylesheet has been placed in the public domain.
-
-Default cascading style sheet for the HTML output of Docutils.
-
-See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
-customize this style sheet.
-*/
-
-/* used to remove borders from tables and images */
-.borderless, table.borderless td, table.borderless th {
-  border: 0 }
-
-table.borderless td, table.borderless th {
-  /* Override padding for "table.docutils td" with "! important".
-     The right padding separates the table cells. */
-  padding: 0 0.5em 0 0 ! important }
-
-.first {
-  /* Override more specific margin styles with "! important". */
-  margin-top: 0 ! important }
-
-.last, .with-subtitle {
-  margin-bottom: 0 ! important }
-
-.hidden {
-  display: none }
-
-a.toc-backref {
-  text-decoration: none ;
-  color: black }
-
-blockquote.epigraph {
-  margin: 2em 5em ; }
-
-dl.docutils dd {
-  margin-bottom: 0.5em }
-
-object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
-  overflow: hidden;
-}
-
-/* Uncomment (and remove this text!) to get bold-faced definition list terms
-dl.docutils dt {
-  font-weight: bold }
-*/
-
-div.abstract {
-  margin: 2em 5em }
-
-div.abstract p.topic-title {
-  font-weight: bold ;
-  text-align: center }
-
-div.admonition, div.attention, div.caution, div.danger, div.error,
-div.hint, div.important, div.note, div.tip, div.warning {
-  margin: 2em ;
-  border: medium outset ;
-  padding: 1em }
-
-div.admonition p.admonition-title, div.hint p.admonition-title,
-div.important p.admonition-title, div.note p.admonition-title,
-div.tip p.admonition-title {
-  font-weight: bold ;
-  font-family: sans-serif }
-
-div.attention p.admonition-title, div.caution p.admonition-title,
-div.danger p.admonition-title, div.error p.admonition-title,
-div.warning p.admonition-title {
-  color: red ;
-  font-weight: bold ;
-  font-family: sans-serif }
-
-/* Uncomment (and remove this text!) to get reduced vertical space in
-   compound paragraphs.
-div.compound .compound-first, div.compound .compound-middle {
-  margin-bottom: 0.5em }
-
-div.compound .compound-last, div.compound .compound-middle {
-  margin-top: 0.5em }
-*/
-
-div.dedication {
-  margin: 2em 5em ;
-  text-align: center ;
-  font-style: italic }
-
-div.dedication p.topic-title {
-  font-weight: bold ;
-  font-style: normal }
-
-div.figure {
-  margin-left: 2em ;
-  margin-right: 2em }
-
-div.footer, div.header {
-  clear: both;
-  font-size: smaller }
-
-div.line-block {
-  display: block ;
-  margin-top: 1em ;
-  margin-bottom: 1em }
-
-div.line-block div.line-block {
-  margin-top: 0 ;
-  margin-bottom: 0 ;
-  margin-left: 1.5em }
-
-div.sidebar {
-  margin: 0 0 0.5em 1em ;
-  border: medium outset ;
-  padding: 1em ;
-  background-color: #ffffee ;
-  width: 40% ;
-  float: right ;
-  clear: right }
-
-div.sidebar p.rubric {
-  font-family: sans-serif ;
-  font-size: medium }
-
-div.system-messages {
-  margin: 5em }
-
-div.system-messages h1 {
-  color: red }
-
-div.system-message {
-  border: medium outset ;
-  padding: 1em }
-
-div.system-message p.system-message-title {
-  color: red ;
-  font-weight: bold }
-
-div.topic {
-  margin: 2em }
-
-h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
-h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
-  margin-top: 0.4em }
-
-h1.title {
-  text-align: center }
-
-h2.subtitle {
-  text-align: center }
-
-hr.docutils {
-  width: 75% }
-
-img.align-left, .figure.align-left, object.align-left {
-  clear: left ;
-  float: left ;
-  margin-right: 1em }
-
-img.align-right, .figure.align-right, object.align-right {
-  clear: right ;
-  float: right ;
-  margin-left: 1em }
-
-img.align-center, .figure.align-center, object.align-center {
-  display: block;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-.align-left {
-  text-align: left }
-
-.align-center {
-  clear: both ;
-  text-align: center }
-
-.align-right {
-  text-align: right }
-
-/* reset inner alignment in figures */
-div.align-right {
-  text-align: inherit }
-
-/* div.align-center * { */
-/*   text-align: left } */
-
-ol.simple, ul.simple {
-  margin-bottom: 1em }
-
-ol.arabic {
-  list-style: decimal }
-
-ol.loweralpha {
-  list-style: lower-alpha }
-
-ol.upperalpha {
-  list-style: upper-alpha }
-
-ol.lowerroman {
-  list-style: lower-roman }
-
-ol.upperroman {
-  list-style: upper-roman }
-
-p.attribution {
-  text-align: right ;
-  margin-left: 50% }
-
-p.caption {
-  font-style: italic }
-
-p.credits {
-  font-style: italic ;
-  font-size: smaller }
-
-p.label {
-  white-space: nowrap }
-
-p.rubric {
-  font-weight: bold ;
-  font-size: larger ;
-  color: maroon ;
-  text-align: center }
-
-p.sidebar-title {
-  font-family: sans-serif ;
-  font-weight: bold ;
-  font-size: larger }
-
-p.sidebar-subtitle {
-  font-family: sans-serif ;
-  font-weight: bold }
-
-p.topic-title {
-  font-weight: bold }
-
-pre.address {
-  margin-bottom: 0 ;
-  margin-top: 0 ;
-  font: inherit }
-
-pre.literal-block, pre.doctest-block, pre.math {
-  margin-left: 2em ;
-  margin-right: 2em }
-
-span.classifier {
-  font-family: sans-serif ;
-  font-style: oblique }
-
-span.classifier-delimiter {
-  font-family: sans-serif ;
-  font-weight: bold }
-
-span.interpreted {
-  font-family: sans-serif }
-
-span.option {
-  white-space: nowrap }
-
-span.pre {
-  white-space: pre }
-
-span.problematic {
-  color: red }
-
-span.section-subtitle {
-  /* font-size relative to parent (h1..h6 element) */
-  font-size: 80% }
-
-table.citation {
-  border-left: solid 1px gray;
-  margin-left: 1px }
-
-table.docinfo {
-  margin: 2em 4em }
-
-table.docutils {
-  margin-top: 0.5em ;
-  margin-bottom: 0.5em }
-
-table.footnote {
-  border-left: solid 1px black;
-  margin-left: 1px }
-
-table.docutils td, table.docutils th,
-table.docinfo td, table.docinfo th {
-  padding-left: 0.5em ;
-  padding-right: 0.5em ;
-  vertical-align: top }
-
-table.docutils th.field-name, table.docinfo th.docinfo-name {
-  font-weight: bold ;
-  text-align: left ;
-  white-space: nowrap ;
-  padding-left: 0 }
-
-h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
-h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
-  font-size: 100% }
-
-ul.auto-toc {
-  list-style-type: none }
-
-</style>
-</head>
-<body>
-<div class="document" id="designing-and-testing-pyzmq-applications-part-1">
-<h1 class="title">Designing and Testing PyZMQ Applications – Part 1</h1>
-
-<p><a class="reference external" href="http://www.zeromq.org/">ZeroMQ</a> (or ØMQ or ZMQ) is an intelligent messaging
-framework and <a class="reference external" href="http://zguide.zeromq.org/page:all#Fixing-the-World">described</a>
-as “sockets on steroids”. That is, they look like normal TCP sockets but
-actually work as you’d expect sockets to work. <a class="reference external" href="http://www.zeromq.org/bindings:python">PyZMQ</a> adds even more convenience to them,
-which makes it a really a good choice if you want to implement a distributed
-application. Another big plus for ØMQ is that you can integrate sub-systems
-written in C, Java or any other language ØMQ supports (which are a lot).</p>
-<p>If you’ve never heard of ØMQ before, I recommend to read <a class="reference external" href="http://nichol.as/zeromq-an-introduction">ZeroMQ an
-Introduction</a> by Nicholas Piël,
-before you go on with this article.</p>
-<p>The <a class="reference external" href="http://zguide.zeromq.org/page:all">ØMQ Guide</a> and <a class="reference external" href="http://zeromq.github.com/pyzmq/">PyZMQ’s documentation</a> are really good, so you can easily get
-started. However, when we began to implement a larger application with it (a
-distributed simulation framework), several questions arose which were not
-covered by the documentation:</p>
-<ul class="simple">
-<li>What’s the best way do design our application?</li>
-<li>How can we keep it readable, flexible and maintainable?</li>
-<li>How do we test it?</li>
-</ul>
-<p>I didn’t find something like a best practice article that answered my
-questions. So in this series of articles, I’m going to talk about what I’ve
-learned during the last months. I’m not a PyZMQ expert (yet ;-)), but what I’ve
-done so far works quite well and I never had more tests in a project than I do
-have now.</p>
-<p>You’ll find the source for the examples at <a class="reference external" href="https://bitbucket.org/ssc/pyzmq-article">bitbucket</a>. They are written in Python 3.2 and
-tested under Mac OS X Lion, Ubuntu 11.10 and Windows 7, 64 bit in each case.
-If you have any suggestions or improvements, please fork me or just leave a
-<a class="reference external" href="#comments">comment</a>.</p>
-<p>In this first article, I’m going to talk a bit about how you could generally
-design your application to be flexible, maintainable and testable. The second
-part will be about unit testing and the finally, I’ll cover process and system
-testing.</p>
-<div class="section" id="comparison-of-different-approaches">
-<h1>Comparison of Different Approaches</h1>
-<p>There are basically three possible ways to implement a PyZMQ application. One,
-that’s easy, but limited in practical use, one that’s more flexible, but not
-really pythonic and one, that needs a bit more setup, but is flexible and
-pythonic.</p>
-<p>All three examples feature a simple ping process and a pong process with
-varying complexity. I use multiprocessing to run the pong process, because
-that’s what you should usually do in real PyZMQ applications (you don’t want to
-use threads and if both processes are running on the same machine, there’s no
-need to invoke both of them separately).</p>
-<p>All of the examples will have the following output:</p>
-<div class="highlight"><pre><span class="o">(</span>zmq<span class="o">)</span><span class="nv">$ </span>python blocking_recv.py
-Pong got request: ping 0
-Ping got reply: pong 0
-...
-Pong got request: ping 4
-Ping got reply: pong 4
-</pre></div>
-<p>Let’s start with the easy one first. You just use on of the socket’s recv
-methods in a loop:</p>
-<div class="highlight"><pre><span class="c"># blocking_recv.py</span>
-<span class="kn">import</span> <span class="nn">multiprocessing</span>
-<span class="kn">import</span> <span class="nn">zmq</span>
-
-
-<span class="n">addr</span> <span class="o">=</span> <span class="s">&#39;tcp://127.0.0.1:5678&#39;</span>
-
-
-<span class="k">def</span> <span class="nf">ping</span><span class="p">():</span>
-    <span class="sd">&quot;&quot;&quot;Sends ping requests and waits for replies.&quot;&quot;&quot;</span>
-    <span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
-    <span class="n">sock</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">REQ</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="n">addr</span><span class="p">)</span>
-
-    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
-        <span class="n">sock</span><span class="o">.</span><span class="n">send_unicode</span><span class="p">(</span><span class="s">&#39;ping </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">i</span><span class="p">)</span>
-        <span class="n">rep</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv_unicode</span><span class="p">()</span>  <span class="c"># This blocks until we get something</span>
-        <span class="k">print</span><span class="p">(</span><span class="s">&#39;Ping got reply:&#39;</span><span class="p">,</span> <span class="n">rep</span><span class="p">)</span>
-
-
-<span class="k">def</span> <span class="nf">pong</span><span class="p">():</span>
-    <span class="sd">&quot;&quot;&quot;Waits for ping requests and replies with a pong.&quot;&quot;&quot;</span>
-    <span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
-    <span class="n">sock</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">REP</span><span class="p">)</span>
-    <span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span>
-
-    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
-        <span class="n">req</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv_unicode</span><span class="p">()</span>  <span class="c"># This also blocks</span>
-        <span class="k">print</span><span class="p">(</span><span class="s">&#39;Pong got request:&#39;</span><span class="p">,</span> <span class="n">req</span><span class="p">)</span>
-        <span class="n">sock</span><span class="o">.</span><span class="n">send_unicode</span><span class="p">(</span><span class="s">&#39;pong </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">i</span><span class="p">)</span>
-
-
-<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
-    <span class="n">pong_proc</span> <span class="o">=</span> <span class="n">multiprocessing</span><span class="o">.</span><span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">pong</span><span class="p">)</span>
-    <span class="n">pong_proc</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
-
-    <span class="n">ping</span><span class="p">()</span>
-
-    <span class="n">pong_proc</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
-</pre></div>
-<p>So this is very easy and no that much code. The problem with this is, that it
-only works well if your process only uses one socket. Unfortunately, in larger
-applications that is rather rarely the case.</p>
-<p>A way to handle multiple sockets per process is polling. In addition to your
-context and socket(s), you need a <em>poller</em>. You also have to tell it which
-events on which socket you are going to poll:</p>
-<div class="highlight"><pre><span class="c"># polling.py</span>
-<span class="k">def</span> <span class="nf">pong</span><span class="p">():</span>
-    <span class="sd">&quot;&quot;&quot;Waits for ping requests and replies with a pong.&quot;&quot;&quot;</span>
-    <span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
-    <span class="n">sock</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">REP</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="n">addr</span><span class="p">)</span>
-
-    <span class="c"># Create a poller and register the events we want to poll</span>
-    <span class="n">poller</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Poller</span><span class="p">()</span>
-    <span class="n">poller</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">zmq</span><span class="o">.</span><span class="n">POLLIN</span><span class="o">|</span><span class="n">zmq</span><span class="o">.</span><span class="n">POLLOUT</span><span class="p">)</span>
-
-    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
-        <span class="c"># Get all sockets that can do something</span>
-        <span class="n">socks</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">poller</span><span class="o">.</span><span class="n">poll</span><span class="p">())</span>
-
-        <span class="c"># Check if we can receive something</span>
-        <span class="k">if</span> <span class="n">sock</span> <span class="ow">in</span> <span class="n">socks</span> <span class="ow">and</span> <span class="n">socks</span><span class="p">[</span><span class="n">sock</span><span class="p">]</span> <span class="o">==</span> <span class="n">zmq</span><span class="o">.</span><span class="n">POLLIN</span><span class="p">:</span>
-            <span class="n">req</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv_unicode</span><span class="p">()</span>
-            <span class="k">print</span><span class="p">(</span><span class="s">&#39;Pong got request:&#39;</span><span class="p">,</span> <span class="n">req</span><span class="p">)</span>
-
-        <span class="c"># Check if we cann send something</span>
-        <span class="k">if</span> <span class="n">sock</span> <span class="ow">in</span> <span class="n">socks</span> <span class="ow">and</span> <span class="n">socks</span><span class="p">[</span><span class="n">sock</span><span class="p">]</span> <span class="o">==</span> <span class="n">zmq</span><span class="o">.</span><span class="n">POLLOUT</span><span class="p">:</span>
-            <span class="n">sock</span><span class="o">.</span><span class="n">send_unicode</span><span class="p">(</span><span class="s">&#39;pong </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span> <span class="o">//</span> <span class="mi">2</span><span class="p">))</span>
-
-    <span class="n">poller</span><span class="o">.</span><span class="n">unregister</span><span class="p">(</span><span class="n">sock</span><span class="p">)</span>
-</pre></div>
-<p>You see, that our <em>pong</em> function got pretty ugly. You need 10 iterations to do
-five ping-pongs, because in each iteration you can either send or reply. And
-each socket you add to your process adds two more if-statements. You could
-improve that design if you created a base class wrapping the polling loop and
-just register sockets and callbacks in an inheriting class.</p>
-<p>That brings us to our final example. PyZMQ comes with with an <a class="reference external" href="http://zeromq.github.com/pyzmq/eventloop.html">adapted Tornado
-eventloop</a> that handles the
-polling and works with <a class="reference external" href="http://zeromq.github.com/pyzmq/api/generated/zmq.eventloop.zmqstream.html#zmq.eventloop.zmqstream.ZMQStream">ZMQStreams</a>,
-that wrap sockets and add some functionality:</p>
-<div class="highlight"><pre><span class="c"># eventloop.py</span>
-<span class="kn">from</span> <span class="nn">zmq.eventloop</span> <span class="kn">import</span> <span class="n">ioloop</span><span class="p">,</span> <span class="n">zmqstream</span>
-
-
-<span class="k">class</span> <span class="nc">Pong</span><span class="p">(</span><span class="n">multiprocessing</span><span class="o">.</span><span class="n">Process</span><span class="p">):</span>
-    <span class="sd">&quot;&quot;&quot;Waits for ping requests and replies with a pong.&quot;&quot;&quot;</span>
-    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
-        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span> <span class="o">=</span> <span class="bp">None</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">stream</span> <span class="o">=</span> <span class="bp">None</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
-
-    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
-        <span class="sd">&quot;&quot;&quot;</span>
-<span class="sd">        Initializes the event loop, creates the sockets/streams and</span>
-<span class="sd">        starts the (blocking) loop.</span>
-
-<span class="sd">        &quot;&quot;&quot;</span>
-        <span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span> <span class="o">=</span> <span class="n">ioloop</span><span class="o">.</span><span class="n">IOLoop</span><span class="o">.</span><span class="n">instance</span><span class="p">()</span>  <span class="c"># This is the event loop</span>
-
-        <span class="n">sock</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">REP</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="n">addr</span><span class="p">)</span>
-        <span class="c"># We need to create a stream from our socket and</span>
-        <span class="c"># register a callback for recv events.</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">stream</span> <span class="o">=</span> <span class="n">zmqstream</span><span class="o">.</span><span class="n">ZMQStream</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="p">)</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">stream</span><span class="o">.</span><span class="n">on_recv</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handle_ping</span><span class="p">)</span>
-
-        <span class="c"># Start the loop. It runs until we stop it.</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
-
-    <span class="k">def</span> <span class="nf">handle_ping</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">msg</span><span class="p">):</span>
-        <span class="sd">&quot;&quot;&quot;Handles ping requests and sends back a pong.&quot;&quot;&quot;</span>
-        <span class="c"># req is a list of byte objects</span>
-        <span class="n">req</span> <span class="o">=</span> <span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">decode</span><span class="p">()</span>
-        <span class="k">print</span><span class="p">(</span><span class="s">&#39;Pong got request:&#39;</span><span class="p">,</span> <span class="n">req</span><span class="p">)</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">stream</span><span class="o">.</span><span class="n">send_unicode</span><span class="p">(</span><span class="s">&#39;pong </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">i</span><span class="p">)</span>
-
-        <span class="c"># We’ll stop the loop after 5 pings</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
-        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">i</span> <span class="o">==</span> <span class="mi">5</span><span class="p">:</span>
-            <span class="bp">self</span><span class="o">.</span><span class="n">stream</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
-            <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
-</pre></div>
-<p>This even adds more boilerplate code, but it will pay of if you use more
-sockets and most of that stuff in <em>run()</em> can be put into a base class. Another
-drawback is, that the IOLoop only uses <a class="reference external" href="http://zeromq.github.com/pyzmq/api/generated/zmq.core.socket.html#zmq.core.socket.Socket.recv_multipart">recv_multipart()</a>.
-So you always get a lists of byte strings which you have to decode or
-deserialize on your own. However, you can use all the <em>send</em> methods socket
-offers (like <em>send_unicode()</em> or <em>send_json()</em>). You can also stop the loop
-from within a message handler.</p>
-<p>In the next sections, I’ll discuss how you could implement a PyZMQ process that
-uses the event loop.</p>
-</div>
-<div class="section" id="communication-design">
-<h1>Communication Design</h1>
-<p>Before you start to implement anything, you should think about what kind of
-processes you need in your application and which messages they exchange. You
-should also decide what kind of message format and serialization you want to
-use.</p>
-<p>PyZMQ has built-in support for Unicode (<em>send</em> sends plain C strings which map
-to Python <em>byte</em> objects, so there’s a separate method to send Unicode
-strings), JSON and Pickle.</p>
-<p>JSON is nice, because it’s fast and lets you integrate processes written in
-other languages into you application. It’s also a bit safer, because you cannot
-receive arbitrary objects as with <a class="reference external" href="http://docs.python.org/py3k/library/pickle#restricting-globals">pickle</a>.  The most
-straightforward syntax for JSON messages is to let them be triples <em>[msg_type,
-args, kwargs]</em>, where <em>msg_type</em> maps to a method name and <em>args</em> and <em>kwargs</em>
-get passed as positional and keyword arguments.</p>
-<p>I strongly recommend you to document each chain of messages your application
-sends to perform a certain task. I do this with fancy PowerPoint graphics and
-with even fancier ASCII art in <a class="reference external" href="http://sphinx.pocoo.org">Sphinx</a>. Here is how
-I would document our ping-pong:</p>
-<div class="highlight"><pre><span class="gh">Sending pings</span>
-<span class="gh">-------------</span>
-
-<span class="m">*</span> If the ping process sends a <span class="ge">*ping*</span>, the pong processes responds with a
-  <span class="ge">*pong*</span>.
-<span class="m">*</span> The number of pings (and pongs) is counted. The current ping count is
-  sent with each message.
-
-<span class="se">::</span>
-
-<span class="s">    PingProc      PongProc</span>
-<span class="s">     [REQ] ---1--&gt; [REP]</span>
-<span class="s">           &lt;--2---</span>
-
-
-<span class="s">    1 IN : [&#39;ping, count&#39;]</span>
-<span class="s">    1 OUT: [&#39;ping, count&#39;]</span>
-
-<span class="s">    2 IN : [&#39;pong, count&#39;]</span>
-<span class="s">    2 OUT: [&#39;pong, count&#39;]</span>
-</pre></div>
-<p>First, I write some bullet points that explain how the processes behave and why
-they behave this way. This is followed by some kind of sequence diagram that
-shows when which process sents which message using which socket type. Finally,
-I write down how the messages are looking. <tt class="docutils literal"># IN</tt> is what you would pass to
-<em>send_multipart</em> and <tt class="docutils literal"># OUT</tt> is, what is received on the other side by
-<em>recv_multipart</em>. If one of the participating sockets is a <em>ROUTER</em> or
-<em>DEALER</em>, <em>IN</em> and <em>OUT</em> will differ (though that’s not the case in this
-example). Everything in single quotation marks (<tt class="docutils literal">'</tt>) represents a JSON
-serialized list.</p>
-<p>If our pong process used a <em>ROUTER</em> socket instead of the <em>REP</em> socket, it
-would look like this:</p>
-<pre class="literal-block">
-1 IN : ['ping, count']
-1 OUT: [ping_uuid, '', 'ping, count']
-
-2 IN : [ping_uuid, '', 'pong, count']
-2 OUT: ['pong, count']
-</pre>
-<p>This seems like a lot of tedious work, but trust me, it really helps a lot
-when you need to change something a few weeks later!</p>
-</div>
-<div class="section" id="application-design">
-<h1>Application Design</h1>
-<p>In the examples above, the <em>Pong</em> process was responsible for setting
-everything up, for receiving/sending messages and for the actual application
-logic (counting incoming pings and creating a pong).</p>
-<p>Obviously, this is not a very good design. What we can do about this is to put
-most of that nasty setup stuff into a base class which all your processes can
-inherit from, and to put all the actual application logic into a separate
-(PyZMQ independent) class.</p>
-<div class="section" id="zmqpocess-the-base-class-for-all-processes">
-<h2>ZmqPocess – The Base Class for all Processes</h2>
-<p>The base class basically implements two things:</p>
-<ul class="simple">
-<li>a <em>setup</em> method that creates a context an a loop</li>
-<li>a <em>stream</em> factory method for streams with a <em>on_recv</em> callback. It creates
-a socket and can connect/bind it to a given address or bind it to a random
-port (that’s why it returns the port number in addition to the stream
-itself).</li>
-</ul>
-<p>It also inherits <a class="reference external" href="http://docs.python.org/py3k/library/multiprocessing#process-and-exceptions">multiprocessing.Process</a>
-so that it is easier to spawn it as sub-process. Of course, you can also just
-call its <em>run()</em> method from you <em>main()</em>.</p>
-<div class="highlight"><pre><span class="c"># zmqproc.py</span>
-<span class="kn">import</span> <span class="nn">multiprocessing</span>
-
-<span class="kn">from</span> <span class="nn">zmq.eventloop</span> <span class="kn">import</span> <span class="n">ioloop</span><span class="p">,</span> <span class="n">zmqstream</span>
-<span class="kn">import</span> <span class="nn">zmq</span>
-
-
-<span class="k">class</span> <span class="nc">ZmqProcess</span><span class="p">(</span><span class="n">multiprocessing</span><span class="o">.</span><span class="n">Process</span><span class="p">):</span>
-    <span class="sd">&quot;&quot;&quot;</span>
-<span class="sd">    This is the base for all processes and offers utility functions</span>
-<span class="sd">    for setup and creating new streams.</span>
-
-<span class="sd">    &quot;&quot;&quot;</span>
-    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
-        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span>
-
-        <span class="bp">self</span><span class="o">.</span><span class="n">context</span> <span class="o">=</span> <span class="bp">None</span>
-        <span class="sd">&quot;&quot;&quot;The ØMQ :class:`~zmq.Context` instance.&quot;&quot;&quot;</span>
-
-        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span> <span class="o">=</span> <span class="bp">None</span>
-        <span class="sd">&quot;&quot;&quot;PyZMQ&#39;s event loop (:class:`~zmq.eventloop.ioloop.IOLoop`).&quot;&quot;&quot;</span>
-
-    <span class="k">def</span> <span class="nf">setup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
-        <span class="sd">&quot;&quot;&quot;</span>
-<span class="sd">        Creates a :attr:`context` and an event :attr:`loop` for the process.</span>
-
-<span class="sd">        &quot;&quot;&quot;</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span> <span class="o">=</span> <span class="n">ioloop</span><span class="o">.</span><span class="n">IOLoop</span><span class="o">.</span><span class="n">instance</span><span class="p">()</span>
-
-    <span class="k">def</span> <span class="nf">stream</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sock_type</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="n">bind</span><span class="p">,</span> <span class="n">callback</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">subscribe</span><span class="o">=</span><span class="n">b</span><span class="s">&#39;&#39;</span><span class="p">):</span>
-        <span class="sd">&quot;&quot;&quot;</span>
-<span class="sd">        Creates a :class:`~zmq.eventloop.zmqstream.ZMQStream`.</span>
-
-<span class="sd">        :param sock_type: The ØMQ socket type (e.g. ``zmq.REQ``)</span>
-<span class="sd">        :param addr: Address to bind or connect to formatted as *host:port*,</span>
-<span class="sd">                *(host, port)* or *host* (bind to random port).</span>
-<span class="sd">                If *bind* is ``True``, *host* may be:</span>
-
-<span class="sd">                - the wild-card ``*``, meaning all available interfaces,</span>
-<span class="sd">                - the primary IPv4 address assigned to the interface, in its</span>
-<span class="sd">                  numeric representation or</span>
-<span class="sd">                - the interface name as defined by the operating system.</span>
-
-<span class="sd">                If *bind* is ``False``, *host* may be:</span>
-
-<span class="sd">                - the DNS name of the peer or</span>
-<span class="sd">                - the IPv4 address of the peer, in its numeric representation.</span>
-
-<span class="sd">                If *addr* is just a host name without a port and *bind* is</span>
-<span class="sd">                ``True``, the socket will be bound to a random port.</span>
-<span class="sd">        :param bind: Binds to *addr* if ``True`` or tries to connect to it</span>
-<span class="sd">                otherwise.</span>
-<span class="sd">        :param callback: A callback for</span>
-<span class="sd">                :meth:`~zmq.eventloop.zmqstream.ZMQStream.on_recv`, optional</span>
-<span class="sd">        :param subscribe: Subscription pattern for *SUB* sockets, optional,</span>
-<span class="sd">                defaults to ``b&#39;&#39;``.</span>
-<span class="sd">        :returns: A tuple containg the stream and the port number.</span>
-
-<span class="sd">        &quot;&quot;&quot;</span>
-        <span class="n">sock</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">sock_type</span><span class="p">)</span>
-
-        <span class="c"># addr may be &#39;host:port&#39; or (&#39;host&#39;, port)</span>
-        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
-            <span class="n">addr</span> <span class="o">=</span> <span class="n">addr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;:&#39;</span><span class="p">)</span>
-        <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">addr</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="k">else</span> <span class="p">(</span><span class="n">addr</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="bp">None</span><span class="p">)</span>
-
-        <span class="c"># Bind/connect the socket</span>
-        <span class="k">if</span> <span class="n">bind</span><span class="p">:</span>
-            <span class="k">if</span> <span class="n">port</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="s">&#39;tcp://</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
-            <span class="k">else</span><span class="p">:</span>
-                <span class="n">port</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">bind_to_random_port</span><span class="p">(</span><span class="s">&#39;tcp://</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">host</span><span class="p">)</span>
-        <span class="k">else</span><span class="p">:</span>
-            <span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;tcp://</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
-
-        <span class="c"># Add a default subscription for SUB sockets</span>
-        <span class="k">if</span> <span class="n">sock_type</span> <span class="o">==</span> <span class="n">zmq</span><span class="o">.</span><span class="n">SUB</span><span class="p">:</span>
-            <span class="n">sock</span><span class="o">.</span><span class="n">setsockopt</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">SUBSCRIBE</span><span class="p">,</span> <span class="n">subscribe</span><span class="p">)</span>
-
-        <span class="c"># Create the stream and add the callback</span>
-        <span class="n">stream</span> <span class="o">=</span> <span class="n">zmqstream</span><span class="o">.</span><span class="n">ZMQStream</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="p">)</span>
-        <span class="k">if</span> <span class="n">callback</span><span class="p">:</span>
-            <span class="n">stream</span><span class="o">.</span><span class="n">on_recv</span><span class="p">(</span><span class="n">callback</span><span class="p">)</span>
-
-        <span class="k">return</span> <span class="n">stream</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="section" id="pongproc-the-actual-process">
-<h2>PongProc – The Actual Process</h2>
-<p>The <em>PongProc</em> inherits <em>ZmqProcess</em> and is the main class for our process. It
-creates the streams, starts the event loop and dispatches all messages to the
-appropriate handlers:</p>
-<div class="highlight"><pre><span class="c"># pongproc.py</span>
-<span class="kn">from</span> <span class="nn">zmq.utils</span> <span class="kn">import</span> <span class="n">jsonapi</span> <span class="k">as</span> <span class="n">json</span>
-<span class="kn">import</span> <span class="nn">zmq</span>
-
-<span class="kn">import</span> <span class="nn">zmqproc</span>
-
-
-<span class="n">host</span> <span class="o">=</span> <span class="s">&#39;127.0.0.1&#39;</span>
-<span class="n">port</span> <span class="o">=</span> <span class="mi">5678</span>
-
-
-<span class="k">class</span> <span class="nc">PongProc</span><span class="p">(</span><span class="n">zmqproc</span><span class="o">.</span><span class="n">ZmqProcess</span><span class="p">):</span>
-    <span class="sd">&quot;&quot;&quot;</span>
-<span class="sd">    Main processes for the Ponger. It handles ping requests and sends back</span>
-<span class="sd">    a pong.</span>
-
-<span class="sd">    &quot;&quot;&quot;</span>
-    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bind_addr</span><span class="p">):</span>
-        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span>
-
-        <span class="bp">self</span><span class="o">.</span><span class="n">bind_addr</span> <span class="o">=</span> <span class="n">bind_addr</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">rep_stream</span> <span class="o">=</span> <span class="bp">None</span>
-
-        <span class="c"># Make sure this is pickle-able (e.g., not using threads)</span>
-        <span class="c"># or it won&#39;t work on Windows. If it&#39;s not pickle-able, instantiate</span>
-        <span class="c"># it in setup().</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">ping_handler</span> <span class="o">=</span> <span class="n">PingHandler</span><span class="p">()</span>
-
-    <span class="k">def</span> <span class="nf">setup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
-        <span class="sd">&quot;&quot;&quot;Sets up PyZMQ and creates all streams.&quot;&quot;&quot;</span>
-        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">setup</span><span class="p">()</span>
-
-        <span class="bp">self</span><span class="o">.</span><span class="n">rep_stream</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">stream</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">REP</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">bind_addr</span><span class="p">,</span> <span class="n">bind</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
-                <span class="n">callback</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">handle_rep_stream</span><span class="p">)</span>
-
-    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
-        <span class="sd">&quot;&quot;&quot;Sets up everything and starts the event loop.&quot;&quot;&quot;</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">setup</span><span class="p">()</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
-
-    <span class="k">def</span> <span class="nf">stop</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
-        <span class="sd">&quot;&quot;&quot;Stops the event loop.&quot;&quot;&quot;</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
-
-    <span class="k">def</span> <span class="nf">handle_rep_stream</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">msg</span><span class="p">):</span>
-        <span class="sd">&quot;&quot;&quot;</span>
-<span class="sd">        Handles messages from a Pinger:</span>
-
-<span class="sd">        *ping*</span>
-<span class="sd">            Send back a pong.</span>
-
-<span class="sd">        *plzdiekthxbye*</span>
-<span class="sd">            Stop the ioloop and exit.</span>
-
-<span class="sd">        &quot;&quot;&quot;</span>
-        <span class="n">msg_type</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
-
-        <span class="k">if</span> <span class="n">msg_type</span> <span class="o">==</span> <span class="s">&#39;ping&#39;</span><span class="p">:</span>
-            <span class="n">rep</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ping_handler</span><span class="o">.</span><span class="n">make_pong</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
-            <span class="bp">self</span><span class="o">.</span><span class="n">rep_stream</span><span class="o">.</span><span class="n">send_json</span><span class="p">(</span><span class="n">rep</span><span class="p">)</span>
-
-        <span class="k">elif</span> <span class="n">msg_type</span> <span class="o">==</span> <span class="s">&#39;plzdiekthxbye&#39;</span><span class="p">:</span>
-            <span class="bp">self</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
-
-        <span class="k">else</span><span class="p">:</span>
-            <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s">&#39;Received unkown message type: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">msg_type</span><span class="p">)</span>
-</pre></div>
-<p>There are a couple of things to note here:</p>
-<ul>
-<li><p class="first">I instantiated the <em>PingHandler</em> in the process’ <em>__init__</em> method. If you
-are going to start this process as a sub-process via <em>start</em>, make sure
-everything you instantiate in <em>__init__</em> is pickle-able or it won’t work on
-Windows (Linux and Mac OS X use <em>fork</em> to create a sub-process and <em>fork</em>
-just makes a copy of the main process and gives it a new process ID. <a class="reference external" href="http://docs.python.org/py3k/library/multiprocessing#windows">On
-Windows</a>,
-there is no <em>fork</em> and the context of your main process is pickled and sent
-to the sub-process).</p>
-</li>
-<li><p class="first">In <em>setup</em>, call <tt class="docutils literal"><span class="pre">super().setup()</span></tt> before you create a stream or you
-won’t have a loop instance for them. You don’t call <em>setup</em> in
-the process’ <em>__init__</em>, because the context must be created within the
-new system process. So we call <em>setup</em> in <em>run</em>.</p>
-</li>
-<li><p class="first">The <em>stop</em> method is not really necessary in this example, but it can be used
-to send stop messages to sub-processes when the main process terminates and
-to do other kinds of clean-up. You can also execute it if you except a
-<tt class="docutils literal">KeyboardInterrupt</tt> after calling <em>run</em>.</p>
-</li>
-<li><p class="first"><em>handle_rep_stream</em> is the message dispatcher for the process’ <em>REP</em> stream.
-It parses the message and calls the appropriate handler for that message (or
-raises an error if the message type is invalid). If your <em>if</em> and <em>elif</em>
-statements all do the same, you might consider replacing them with a dict
-that contains the handlers for each message type:</p>
-<div class="highlight"><pre><span class="n">handlers</span> <span class="o">=</span> <span class="p">{</span>
-    <span class="s">&#39;msg&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">handler_for_msg</span><span class="p">,</span>
-<span class="p">}</span>
-<span class="k">try</span><span class="p">:</span>
-    <span class="n">rep</span> <span class="o">=</span> <span class="n">handlers</span><span class="p">[</span><span class="n">msg_type</span><span class="p">](</span><span class="n">data</span><span class="p">)</span>
-    <span class="bp">self</span><span class="o">.</span><span class="n">rep_stream</span><span class="o">.</span><span class="n">send_multipart</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
-<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
-    <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s">&#39;Received unknown message.&#39;</span><span class="p">)</span>
-</pre></div>
-</li>
-</ul>
-</div>
-<div class="section" id="pinghandler-the-application-logic">
-<h2>PingHandler – The Application Logic</h2>
-<p>The <em>PingHandler</em> contains the actual application logic (which is not much,
-in this example). The <em>make_pong</em> method just gets the number of pings sent
-with the <em>ping</em> message and creates a new <em>pong</em> message. The serialization
-is done by <em>PongProc</em>, so our Handler does not depend on PyZMQ:</p>
-<div class="highlight"><pre><span class="k">class</span> <span class="nc">PingHandler</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
-
-    <span class="k">def</span> <span class="nf">make_pong</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">num_pings</span><span class="p">):</span>
-        <span class="sd">&quot;&quot;&quot;Creates and returns a pong message.&quot;&quot;&quot;</span>
-        <span class="k">print</span><span class="p">(</span><span class="s">&#39;Pong got request number </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">num_pings</span><span class="p">)</span>
-
-        <span class="k">return</span> <span class="p">[</span><span class="s">&#39;pong&#39;</span><span class="p">,</span> <span class="n">num_pings</span><span class="p">]</span>
-</pre></div>
-</div>
-</div>
-<div class="section" id="summary">
-<h1>Summary</h1>
-<p>Okay, that’s it for now. I showed you three ways to use PyZMQ. If you have a
-very simple process with only one socket, you can easily use its blocking
-<em>recv</em> methods. If you need more than one socket, I recommend using the event
-loop. And polling … you don’t want to use that.</p>
-<p>If you decide to use PyZMQ’s event loop, you should separate the application
-logic from all the PyZMQ stuff (like creating streams, sending/receiving
-messages and dispatching them). If your application consists of more then one
-process (which is usually the case), you should also create a base class with
-shared functionality for them.</p>
-<p>In the next part, I’m going to talk about how you can test your application.</p>
-</div>
-</div>
-</body>
-</html>

File article.txt

-
-Designing and Testing PyZMQ Applications – Part 1
-=================================================
-
-`ZeroMQ <http://www.zeromq.org/>`_ (or ØMQ or ZMQ) is an intelligent messaging
-framework and `described <http://zguide.zeromq.org/page:all#Fixing-the-World>`_
-as “sockets on steroids”. That is, they look like normal TCP sockets but
-actually work as you’d expect sockets to work. `PyZMQ
-<http://www.zeromq.org/bindings:python>`_ adds even more convenience to them,
-which makes it a really a good choice if you want to implement a distributed
-application. Another big plus for ØMQ is that you can integrate sub-systems
-written in C, Java or any other language ØMQ supports (which are a lot).
-
-If you’ve never heard of ØMQ before, I recommend to read `ZeroMQ an
-Introduction <http://nichol.as/zeromq-an-introduction>`_ by Nicholas Piël,
-before you go on with this article.
-
-The `ØMQ Guide <http://zguide.zeromq.org/page:all>`_ and `PyZMQ’s documentation
-<http://zeromq.github.com/pyzmq/>`_ are really good, so you can easily get
-started. However, when we began to implement a larger application with it (a
-distributed simulation framework), several questions arose which were not
-covered by the documentation:
-
-- What’s the best way do design our application?
-- How can we keep it readable, flexible and maintainable?
-- How do we test it?
-
-I didn’t find something like a best practice article that answered my
-questions. So in this series of articles, I’m going to talk about what I’ve
-learned during the last months. I’m not a PyZMQ expert (yet ;-)), but what I’ve
-done so far works quite well and I never had more tests in a project than I do
-have now.
-
-You’ll find the source for the examples at `bitbucket
-<https://bitbucket.org/ssc/pyzmq-article>`_. They are written in Python 3.2 and
-tested under Mac OS X Lion, Ubuntu 11.10 and Windows 7, 64 bit in each case.
-If you have any suggestions or improvements, please fork me or just leave a
-`comment <#comments>`_.
-
-In this first article, I’m going to talk a bit about how you could generally
-design your application to be flexible, maintainable and testable. The second
-part will be about unit testing and the finally, I’ll cover process and system
-testing.
-
-
-Comparison of Different Approaches
-----------------------------------
-
-There are basically three possible ways to implement a PyZMQ application. One,
-that’s easy, but limited in practical use, one that’s more flexible, but not
-really pythonic and one, that needs a bit more setup, but is flexible and
-pythonic.
-
-All three examples feature a simple ping process and a pong process with
-varying complexity. I use multiprocessing to run the pong process, because
-that’s what you should usually do in real PyZMQ applications (you don’t want to
-use threads and if both processes are running on the same machine, there’s no
-need to invoke both of them separately).
-
-All of the examples will have the following output:
-
-.. code-block::  bash
-
-    (zmq)$ python blocking_recv.py
-    Pong got request: ping 0
-    Ping got reply: pong 0
-    ...
-    Pong got request: ping 4
-    Ping got reply: pong 4
-
-Let’s start with the easy one first. You just use on of the socket’s recv
-methods in a loop:
-
-.. code-block:: python
-
-    # blocking_recv.py
-    import multiprocessing
-    import zmq
-
-
-    addr = 'tcp://127.0.0.1:5678'
-
-
-    def ping():
-        """Sends ping requests and waits for replies."""
-        context = zmq.Context()
-        sock = context.socket(zmq.REQ)
-        sock.bind(addr)
-
-        for i in range(5):
-            sock.send_unicode('ping %s' % i)
-            rep = sock.recv_unicode()  # This blocks until we get something
-            print('Ping got reply:', rep)
-
-
-    def pong():
-        """Waits for ping requests and replies with a pong."""
-        context = zmq.Context()
-        sock = context.socket(zmq.REP)
-        sock.connect(addr)
-
-        for i in range(5):
-            req = sock.recv_unicode()  # This also blocks
-            print('Pong got request:', req)
-            sock.send_unicode('pong %s' % i)
-
-
-    if __name__ == '__main__':
-        pong_proc = multiprocessing.Process(target=pong)
-        pong_proc.start()
-
-        ping()
-
-        pong_proc.join()
-
-
-So this is very easy and no that much code. The problem with this is, that it
-only works well if your process only uses one socket. Unfortunately, in larger
-applications that is rather rarely the case.
-
-A way to handle multiple sockets per process is polling. In addition to your
-context and socket(s), you need a *poller*. You also have to tell it which
-events on which socket you are going to poll:
-
-.. code-block:: python
-
-    # polling.py
-    def pong():
-        """Waits for ping requests and replies with a pong."""
-        context = zmq.Context()
-        sock = context.socket(zmq.REP)
-        sock.bind(addr)
-
-        # Create a poller and register the events we want to poll
-        poller = zmq.Poller()
-        poller.register(sock, zmq.POLLIN|zmq.POLLOUT)
-
-        for i in range(10):
-            # Get all sockets that can do something
-            socks = dict(poller.poll())
-
-            # Check if we can receive something
-            if sock in socks and socks[sock] == zmq.POLLIN:
-                req = sock.recv_unicode()
-                print('Pong got request:', req)
-
-            # Check if we cann send something
-            if sock in socks and socks[sock] == zmq.POLLOUT:
-                sock.send_unicode('pong %s' % (i // 2))
-
-        poller.unregister(sock)
-
-
-You see, that our *pong* function got pretty ugly. You need 10 iterations to do
-five ping-pongs, because in each iteration you can either send or reply. And
-each socket you add to your process adds two more if-statements. You could
-improve that design if you created a base class wrapping the polling loop and
-just register sockets and callbacks in an inheriting class.
-
-That brings us to our final example. PyZMQ comes with with an `adapted Tornado
-eventloop <http://zeromq.github.com/pyzmq/eventloop.html>`_ that handles the
-polling and works with `ZMQStreams
-<http://zeromq.github.com/pyzmq/api/generated/zmq.eventloop.zmqstream.html#zmq.eventloop.zmqstream.ZMQStream>`_,
-that wrap sockets and add some functionality:
-
-.. code-block:: python
-
-    # eventloop.py
-    from zmq.eventloop import ioloop, zmqstream
-
-
-    class Pong(multiprocessing.Process):
-        """Waits for ping requests and replies with a pong."""
-        def __init__(self):
-            super().__init__()
-            self.loop = None
-            self.stream = None
-            self.i = 0
-
-        def run(self):
-            """
-            Initializes the event loop, creates the sockets/streams and
-            starts the (blocking) loop.
-
-            """
-            context = zmq.Context()
-            self.loop = ioloop.IOLoop.instance()  # This is the event loop
-
-            sock = context.socket(zmq.REP)
-            sock.bind(addr)
-            # We need to create a stream from our socket and
-            # register a callback for recv events.
-            self.stream = zmqstream.ZMQStream(sock, self.loop)
-            self.stream.on_recv(self.handle_ping)
-
-            # Start the loop. It runs until we stop it.
-            self.loop.start()
-
-        def handle_ping(self, msg):
-            """Handles ping requests and sends back a pong."""
-            # req is a list of byte objects
-            req = msg[0].decode()
-            print('Pong got request:', req)
-            self.stream.send_unicode('pong %s' % self.i)
-
-            # We’ll stop the loop after 5 pings
-            self.i += 1
-            if self.i == 5:
-                self.stream.flush()
-                self.loop.stop()
-
-
-This even adds more boilerplate code, but it will pay of if you use more
-sockets and most of that stuff in *run()* can be put into a base class. Another
-drawback is, that the IOLoop only uses `recv_multipart()
-<http://zeromq.github.com/pyzmq/api/generated/zmq.core.socket.html#zmq.core.socket.Socket.recv_multipart>`_.
-So you always get a lists of byte strings which you have to decode or
-deserialize on your own. However, you can use all the *send* methods socket
-offers (like *send_unicode()* or *send_json()*). You can also stop the loop
-from within a message handler.
-
-In the next sections, I’ll discuss how you could implement a PyZMQ process that
-uses the event loop.
-
-
-Communication Design
---------------------
-
-Before you start to implement anything, you should think about what kind of
-processes you need in your application and which messages they exchange. You
-should also decide what kind of message format and serialization you want to
-use.
-
-PyZMQ has built-in support for Unicode (*send* sends plain C strings which map
-to Python *byte* objects, so there’s a separate method to send Unicode
-strings), JSON and Pickle.
-
-JSON is nice, because it’s fast and lets you integrate processes written in
-other languages into you application. It’s also a bit safer, because you cannot
-receive arbitrary objects as with `pickle
-<http://docs.python.org/py3k/library/pickle#restricting-globals>`_.  The most
-straightforward syntax for JSON messages is to let them be triples *[msg_type,
-args, kwargs]*, where *msg_type* maps to a method name and *args* and *kwargs*
-get passed as positional and keyword arguments.
-
-I strongly recommend you to document each chain of messages your application
-sends to perform a certain task. I do this with fancy PowerPoint graphics and
-with even fancier ASCII art in `Sphinx <http://sphinx.pocoo.org>`_. Here is how
-I would document our ping-pong:
-
-.. code-block:: rst
-
-    Sending pings
-    -------------
-
-    * If the ping process sends a *ping*, the pong processes responds with a
-      *pong*.
-    * The number of pings (and pongs) is counted. The current ping count is
-      sent with each message.
-
-    ::
-
-        PingProc      PongProc
-         [REQ] ---1--> [REP]
-               <--2---
-
-
-        1 IN : ['ping, count']
-        1 OUT: ['ping, count']
-
-        2 IN : ['pong, count']
-        2 OUT: ['pong, count']
-
-First, I write some bullet points that explain how the processes behave and why
-they behave this way. This is followed by some kind of sequence diagram that
-shows when which process sents which message using which socket type. Finally,
-I write down how the messages are looking. ``# IN`` is what you would pass to
-*send_multipart* and ``# OUT`` is, what is received on the other side by
-*recv_multipart*. If one of the participating sockets is a *ROUTER* or
-*DEALER*, *IN* and *OUT* will differ (though that’s not the case in this
-example). Everything in single quotation marks (``'``) represents a JSON
-serialized list.
-
-If our pong process used a *ROUTER* socket instead of the *REP* socket, it
-would look like this::
-
-    1 IN : ['ping, count']
-    1 OUT: [ping_uuid, '', 'ping, count']
-
-    2 IN : [ping_uuid, '', 'pong, count']
-    2 OUT: ['pong, count']
-
-
-This seems like a lot of tedious work, but trust me, it really helps a lot
-when you need to change something a few weeks later!
-
-
-Application Design
-------------------
-
-In the examples above, the *Pong* process was responsible for setting
-everything up, for receiving/sending messages and for the actual application
-logic (counting incoming pings and creating a pong).
-
-Obviously, this is not a very good design. What we can do about this is to put
-most of that nasty setup stuff into a base class which all your processes can
-inherit from, and to put all the actual application logic into a separate
-(PyZMQ independent) class.
-
-ZmqPocess – The Base Class for all Processes
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The base class basically implements two things:
-
-- a *setup* method that creates a context an a loop
-- a *stream* factory method for streams with a *on_recv* callback. It creates
-  a socket and can connect/bind it to a given address or bind it to a random
-  port (that’s why it returns the port number in addition to the stream
-  itself).
-
-It also inherits `multiprocessing.Process
-<http://docs.python.org/py3k/library/multiprocessing#process-and-exceptions>`_
-so that it is easier to spawn it as sub-process. Of course, you can also just
-call its *run()* method from you *main()*.
-
-.. code-block:: python
-
-    # zmqproc.py
-    import multiprocessing
-
-    from zmq.eventloop import ioloop, zmqstream
-    import zmq
-
-
-    class ZmqProcess(multiprocessing.Process):
-        """
-        This is the base for all processes and offers utility functions
-        for setup and creating new streams.
-
-        """
-        def __init__(self):
-            super().__init__()
-
-            self.context = None
-            """The ØMQ :class:`~zmq.Context` instance."""
-
-            self.loop = None
-            """PyZMQ's event loop (:class:`~zmq.eventloop.ioloop.IOLoop`)."""
-
-        def setup(self):
-            """
-            Creates a :attr:`context` and an event :attr:`loop` for the process.
-
-            """
-            self.context = zmq.Context()
-            self.loop = ioloop.IOLoop.instance()
-
-        def stream(self, sock_type, addr, bind, callback=None, subscribe=b''):
-            """
-            Creates a :class:`~zmq.eventloop.zmqstream.ZMQStream`.
-
-            :param sock_type: The ØMQ socket type (e.g. ``zmq.REQ``)
-            :param addr: Address to bind or connect to formatted as *host:port*,
-                    *(host, port)* or *host* (bind to random port).
-                    If *bind* is ``True``, *host* may be:
-
-                    - the wild-card ``*``, meaning all available interfaces,
-                    - the primary IPv4 address assigned to the interface, in its
-                      numeric representation or
-                    - the interface name as defined by the operating system.
-
-                    If *bind* is ``False``, *host* may be:
-
-                    - the DNS name of the peer or
-                    - the IPv4 address of the peer, in its numeric representation.
-
-                    If *addr* is just a host name without a port and *bind* is
-                    ``True``, the socket will be bound to a random port.
-            :param bind: Binds to *addr* if ``True`` or tries to connect to it
-                    otherwise.
-            :param callback: A callback for
-                    :meth:`~zmq.eventloop.zmqstream.ZMQStream.on_recv`, optional
-            :param subscribe: Subscription pattern for *SUB* sockets, optional,
-                    defaults to ``b''``.
-            :returns: A tuple containg the stream and the port number.
-
-            """
-            sock = self.context.socket(sock_type)
-
-            # addr may be 'host:port' or ('host', port)
-            if isinstance(addr, str):
-                addr = addr.split(':')
-            host, port = addr if len(addr) == 2 else (addr[0], None)
-
-            # Bind/connect the socket
-            if bind:
-                if port:
-                    sock.bind('tcp://%s:%s' % (host, port))
-                else:
-                    port = sock.bind_to_random_port('tcp://%s' % host)
-            else:
-                sock.connect('tcp://%s:%s' % (host, port))
-
-            # Add a default subscription for SUB sockets
-            if sock_type == zmq.SUB:
-                sock.setsockopt(zmq.SUBSCRIBE, subscribe)
-
-            # Create the stream and add the callback
-            stream = zmqstream.ZMQStream(sock, self.loop)
-            if callback:
-                stream.on_recv(callback)
-
-            return stream, int(port)
-
-
-PongProc – The Actual Process
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The *PongProc* inherits *ZmqProcess* and is the main class for our process. It
-creates the streams, starts the event loop and dispatches all messages to the
-appropriate handlers:
-
-.. code-block:: python
-
-    # pongproc.py
-    from zmq.utils import jsonapi as json
-    import zmq
-
-    import zmqproc
-
-
-    host = '127.0.0.1'
-    port = 5678
-
-
-    class PongProc(zmqproc.ZmqProcess):
-        """
-        Main processes for the Ponger. It handles ping requests and sends back
-        a pong.
-
-        """
-        def __init__(self, bind_addr):
-            super().__init__()
-
-            self.bind_addr = bind_addr
-            self.rep_stream = None
-
-            # Make sure this is pickle-able (e.g., not using threads)
-            # or it won't work on Windows. If it's not pickle-able, instantiate
-            # it in setup().
-            self.ping_handler = PingHandler()
-
-        def setup(self):
-            """Sets up PyZMQ and creates all streams."""
-            super().setup()
-
-            self.rep_stream, _ = self.stream(zmq.REP, self.bind_addr, bind=True,
-                    callback=self.handle_rep_stream)
-
-        def run(self):
-            """Sets up everything and starts the event loop."""
-            self.setup()
-            self.loop.start()
-
-        def stop(self):
-            """Stops the event loop."""
-            self.loop.stop()
-
-        def handle_rep_stream(self, msg):
-            """
-            Handles messages from a Pinger:
-
-            *ping*
-                Send back a pong.
-
-            *plzdiekthxbye*
-                Stop the ioloop and exit.
-
-            """
-            msg_type, data = json.loads(msg[0])
-
-            if msg_type == 'ping':
-                rep = self.ping_handler.make_pong(data)
-                self.rep_stream.send_json(rep)
-
-            elif msg_type == 'plzdiekthxbye':
-                self.stop()
-
-            else:
-                raise RuntimeError('Received unkown message type: %s' % msg_type)
-
-There are a couple of things to note here:
-
-- I instantiated the *PingHandler* in the process’ *__init__* method. If you
-  are going to start this process as a sub-process via *start*, make sure
-  everything you instantiate in *__init__* is pickle-able or it won’t work on
-  Windows (Linux and Mac OS X use *fork* to create a sub-process and *fork*
-  just makes a copy of the main process and gives it a new process ID. `On
-  Windows <http://docs.python.org/py3k/library/multiprocessing#windows>`_,
-  there is no *fork* and the context of your main process is pickled and sent
-  to the sub-process).
-
-- In *setup*, call ``super().setup()`` before you create a stream or you
-  won’t have a loop instance for them. You don’t call *setup* in
-  the process’ *__init__*, because the context must be created within the
-  new system process. So we call *setup* in *run*.
-
-- The *stop* method is not really necessary in this example, but it can be used
-  to send stop messages to sub-processes when the main process terminates and
-  to do other kinds of clean-up. You can also execute it if you except a
-  ``KeyboardInterrupt`` after calling *run*.
-
-- *handle_rep_stream* is the message dispatcher for the process’ *REP* stream.
-  It parses the message and calls the appropriate handler for that message (or
-  raises an error if the message type is invalid). If your *if* and *elif*
-  statements all do the same, you might consider replacing them with a dict
-  that contains the handlers for each message type:
-
-  .. code-block:: python
-
-    handlers = {
-        'msg': self.handler_for_msg,
-    }
-    try:
-        rep = handlers[msg_type](data)
-        self.rep_stream.send_multipart(msg)
-    except KeyError:
-        raise RuntimeError('Received unknown message.')
-
-PingHandler – The Application Logic
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The *PingHandler* contains the actual application logic (which is not much,
-in this example). The *make_pong* method just gets the number of pings sent
-with the *ping* message and creates a new *pong* message. The serialization
-is done by *PongProc*, so our Handler does not depend on PyZMQ:
-
-.. code-block:: python
-
-    class PingHandler(object):
-
-        def make_pong(self, num_pings):
-            """Creates and returns a pong message."""
-            print('Pong got request number %s' % num_pings)
-
-            return ['pong', num_pings]
-
-
-Summary
--------
-
-Okay, that’s it for now. I showed you three ways to use PyZMQ. If you have a
-very simple process with only one socket, you can easily use its blocking
-*recv* methods. If you need more than one socket, I recommend using the event
-loop. And polling … you don’t want to use that.
-
-If you decide to use PyZMQ’s event loop, you should separate the application
-logic from all the PyZMQ stuff (like creating streams, sending/receiving
-messages and dispatching them). If your application consists of more then one
-process (which is usually the case), you should also create a base class with
-shared functionality for them.
-
-In the next part, I’m going to talk about how you can test your application.

File article_1.html

View file
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.8.1: http://docutils.sourceforge.net/" />
+<title>Designing and Testing PyZMQ Applications – Part 1</title>
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 7056 2011-06-17 10:50:48Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
+  overflow: hidden;
+}
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin: 0 0 0.5em 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left, .figure.align-left, object.align-left {
+  clear: left ;
+  float: left ;
+  margin-right: 1em }
+
+img.align-right, .figure.align-right, object.align-right {
+  clear: right ;
+  float: right ;
+  margin-left: 1em }
+
+img.align-center, .figure.align-center, object.align-center {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.align-left {
+  text-align: left }
+
+.align-center {
+  clear: both ;
+  text-align: center }
+
+.align-right {
+  text-align: right }
+
+/* reset inner alignment in figures */
+div.align-right {
+  text-align: inherit }
+
+/* div.align-center * { */
+/*   text-align: left } */
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font: inherit }
+
+pre.literal-block, pre.doctest-block, pre.math {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="designing-and-testing-pyzmq-applications-part-1">
+<h1 class="title">Designing and Testing PyZMQ Applications – Part 1</h1>
+
+<p><a class="reference external" href="http://www.zeromq.org/">ZeroMQ</a> (or ØMQ or ZMQ) is an intelligent messaging
+framework and <a class="reference external" href="http://zguide.zeromq.org/page:all#Fixing-the-World">described</a>
+as “sockets on steroids”. That is, they look like normal TCP sockets but
+actually work as you’d expect sockets to work. <a class="reference external" href="http://www.zeromq.org/bindings:python">PyZMQ</a> adds even more convenience to them,
+which makes it a really a good choice if you want to implement a distributed
+application. Another big plus for ØMQ is that you can integrate sub-systems
+written in C, Java or any other language ØMQ supports (which are a lot).</p>
+<p>If you’ve never heard of ØMQ before, I recommend to read <a class="reference external" href="http://nichol.as/zeromq-an-introduction">ZeroMQ an
+Introduction</a> by Nicholas Piël,
+before you go on with this article.</p>
+<p>The <a class="reference external" href="http://zguide.zeromq.org/page:all">ØMQ Guide</a> and <a class="reference external" href="http://zeromq.github.com/pyzmq/">PyZMQ’s documentation</a> are really good, so you can easily get
+started. However, when we began to implement a larger application with it (a
+distributed simulation framework), several questions arose which were not
+covered by the documentation:</p>
+<ul class="simple">
+<li>What’s the best way do design our application?</li>
+<li>How can we keep it readable, flexible and maintainable?</li>
+<li>How do we test it?</li>
+</ul>
+<p>I didn’t find something like a best practice article that answered my
+questions. So in this series of articles, I’m going to talk about what I’ve
+learned during the last months. I’m not a PyZMQ expert (yet ;-)), but what I’ve
+done so far works quite well and I never had more tests in a project than I do
+have now.</p>
+<p>You’ll find the source for the examples at <a class="reference external" href="https://bitbucket.org/ssc/pyzmq-article">bitbucket</a>. They are written in Python 3.2 and
+tested under Mac OS X Lion, Ubuntu 11.10 and Windows 7, 64 bit in each case.
+If you have any suggestions or improvements, please fork me or just leave a
+<a class="reference external" href="#comments">comment</a>.</p>
+<p>In this first article, I’m going to talk a bit about how you could generally
+design your application to be flexible, maintainable and testable. The second
+part will be about unit testing and the finally, I’ll cover process and system
+testing.</p>
+<div class="section" id="comparison-of-different-approaches">
+<h1>Comparison of Different Approaches</h1>
+<p>There are basically three possible ways to implement a PyZMQ application. One,
+that’s easy, but limited in practical use, one that’s more flexible, but not
+really pythonic and one, that needs a bit more setup, but is flexible and
+pythonic.</p>
+<p>All three examples feature a simple ping process and a pong process with
+varying complexity. I use multiprocessing to run the pong process, because
+that’s what you should usually do in real PyZMQ applications (you don’t want to
+use threads and if both processes are running on the same machine, there’s no
+need to invoke both of them separately).</p>
+<p>All of the examples will have the following output:</p>
+<div class="highlight"><pre><span class="o">(</span>zmq<span class="o">)</span><span class="nv">$ </span>python blocking_recv.py
+Pong got request: ping 0
+Ping got reply: pong 0
+...
+Pong got request: ping 4
+Ping got reply: pong 4
+</pre></div>
+<p>Let’s start with the easy one first. You just use on of the socket’s recv
+methods in a loop:</p>
+<div class="highlight"><pre><span class="c"># blocking_recv.py</span>
+<span class="kn">import</span> <span class="nn">multiprocessing</span>
+<span class="kn">import</span> <span class="nn">zmq</span>
+
+
+<span class="n">addr</span> <span class="o">=</span> <span class="s">&#39;tcp://127.0.0.1:5678&#39;</span>
+
+
+<span class="k">def</span> <span class="nf">ping</span><span class="p">():</span>
+    <span class="sd">&quot;&quot;&quot;Sends ping requests and waits for replies.&quot;&quot;&quot;</span>
+    <span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
+    <span class="n">sock</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">REQ</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="n">addr</span><span class="p">)</span>
+
+    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
+        <span class="n">sock</span><span class="o">.</span><span class="n">send_unicode</span><span class="p">(</span><span class="s">&#39;ping </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">i</span><span class="p">)</span>
+        <span class="n">rep</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv_unicode</span><span class="p">()</span>  <span class="c"># This blocks until we get something</span>
+        <span class="k">print</span><span class="p">(</span><span class="s">&#39;Ping got reply:&#39;</span><span class="p">,</span> <span class="n">rep</span><span class="p">)</span>
+
+
+<span class="k">def</span> <span class="nf">pong</span><span class="p">():</span>
+    <span class="sd">&quot;&quot;&quot;Waits for ping requests and replies with a pong.&quot;&quot;&quot;</span>
+    <span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
+    <span class="n">sock</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">REP</span><span class="p">)</span>
+    <span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span>
+
+    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
+        <span class="n">req</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv_unicode</span><span class="p">()</span>  <span class="c"># This also blocks</span>
+        <span class="k">print</span><span class="p">(</span><span class="s">&#39;Pong got request:&#39;</span><span class="p">,</span> <span class="n">req</span><span class="p">)</span>
+        <span class="n">sock</span><span class="o">.</span><span class="n">send_unicode</span><span class="p">(</span><span class="s">&#39;pong </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">i</span><span class="p">)</span>
+
+
+<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
+    <span class="n">pong_proc</span> <span class="o">=</span> <span class="n">multiprocessing</span><span class="o">.</span><span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">pong</span><span class="p">)</span>
+    <span class="n">pong_proc</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
+
+    <span class="n">ping</span><span class="p">()</span>
+
+    <span class="n">pong_proc</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
+</pre></div>
+<p>So this is very easy and no that much code. The problem with this is, that it
+only works well if your process only uses one socket. Unfortunately, in larger
+applications that is rather rarely the case.</p>
+<p>A way to handle multiple sockets per process is polling. In addition to your
+context and socket(s), you need a <em>poller</em>. You also have to tell it which
+events on which socket you are going to poll:</p>
+<div class="highlight"><pre><span class="c"># polling.py</span>
+<span class="k">def</span> <span class="nf">pong</span><span class="p">():</span>
+    <span class="sd">&quot;&quot;&quot;Waits for ping requests and replies with a pong.&quot;&quot;&quot;</span>
+    <span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
+    <span class="n">sock</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">REP</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="n">addr</span><span class="p">)</span>
+
+    <span class="c"># Create a poller and register the events we want to poll</span>
+    <span class="n">poller</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Poller</span><span class="p">()</span>
+    <span class="n">poller</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">zmq</span><span class="o">.</span><span class="n">POLLIN</span><span class="o">|</span><span class="n">zmq</span><span class="o">.</span><span class="n">POLLOUT</span><span class="p">)</span>
+
+    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
+        <span class="c"># Get all sockets that can do something</span>
+        <span class="n">socks</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">poller</span><span class="o">.</span><span class="n">poll</span><span class="p">())</span>
+
+        <span class="c"># Check if we can receive something</span>
+        <span class="k">if</span> <span class="n">sock</span> <span class="ow">in</span> <span class="n">socks</span> <span class="ow">and</span> <span class="n">socks</span><span class="p">[</span><span class="n">sock</span><span class="p">]</span> <span class="o">==</span> <span class="n">zmq</span><span class="o">.</span><span class="n">POLLIN</span><span class="p">:</span>
+            <span class="n">req</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv_unicode</span><span class="p">()</span>
+            <span class="k">print</span><span class="p">(</span><span class="s">&#39;Pong got request:&#39;</span><span class="p">,</span> <span class="n">req</span><span class="p">)</span>
+
+        <span class="c"># Check if we cann send something</span>
+        <span class="k">if</span> <span class="n">sock</span> <span class="ow">in</span> <span class="n">socks</span> <span class="ow">and</span> <span class="n">socks</span><span class="p">[</span><span class="n">sock</span><span class="p">]</span> <span class="o">==</span> <span class="n">zmq</span><span class="o">.</span><span class="n">POLLOUT</span><span class="p">:</span>
+            <span class="n">sock</span><span class="o">.</span><span class="n">send_unicode</span><span class="p">(</span><span class="s">&#39;pong </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span> <span class="o">//</span> <span class="mi">2</span><span class="p">))</span>
+
+    <span class="n">poller</span><span class="o">.</span><span class="n">unregister</span><span class="p">(</span><span class="n">sock</span><span class="p">)</span>
+</pre></div>
+<p>You see, that our <em>pong</em> function got pretty ugly. You need 10 iterations to do
+five ping-pongs, because in each iteration you can either send or reply. And
+each socket you add to your process adds two more if-statements. You could
+improve that design if you created a base class wrapping the polling loop and
+just register sockets and callbacks in an inheriting class.</p>
+<p>That brings us to our final example. PyZMQ comes with with an <a class="reference external" href="http://zeromq.github.com/pyzmq/eventloop.html">adapted Tornado
+eventloop</a> that handles the
+polling and works with <a class="reference external" href="http://zeromq.github.com/pyzmq/api/generated/zmq.eventloop.zmqstream.html#zmq.eventloop.zmqstream.ZMQStream">ZMQStreams</a>,
+that wrap sockets and add some functionality:</p>
+<div class="highlight"><pre><span class="c"># eventloop.py</span>
+<span class="kn">from</span> <span class="nn">zmq.eventloop</span> <span class="kn">import</span> <span class="n">ioloop</span><span class="p">,</span> <span class="n">zmqstream</span>
+
+
+<span class="k">class</span> <span class="nc">Pong</span><span class="p">(</span><span class="n">multiprocessing</span><span class="o">.</span><span class="n">Process</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot;Waits for ping requests and replies with a pong.&quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span> <span class="o">=</span> <span class="bp">None</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">stream</span> <span class="o">=</span> <span class="bp">None</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
+
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">        Initializes the event loop, creates the sockets/streams and</span>
+<span class="sd">        starts the (blocking) loop.</span>
+
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span> <span class="o">=</span> <span class="n">ioloop</span><span class="o">.</span><span class="n">IOLoop</span><span class="o">.</span><span class="n">instance</span><span class="p">()</span>  <span class="c"># This is the event loop</span>
+
+        <span class="n">sock</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">REP</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="n">addr</span><span class="p">)</span>
+        <span class="c"># We need to create a stream from our socket and</span>
+        <span class="c"># register a callback for recv events.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">stream</span> <span class="o">=</span> <span class="n">zmqstream</span><span class="o">.</span><span class="n">ZMQStream</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">stream</span><span class="o">.</span><span class="n">on_recv</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handle_ping</span><span class="p">)</span>
+
+        <span class="c"># Start the loop. It runs until we stop it.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
+
+    <span class="k">def</span> <span class="nf">handle_ping</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">msg</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot;Handles ping requests and sends back a pong.&quot;&quot;&quot;</span>
+        <span class="c"># req is a list of byte objects</span>
+        <span class="n">req</span> <span class="o">=</span> <span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">decode</span><span class="p">()</span>
+        <span class="k">print</span><span class="p">(</span><span class="s">&#39;Pong got request:&#39;</span><span class="p">,</span> <span class="n">req</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">stream</span><span class="o">.</span><span class="n">send_unicode</span><span class="p">(</span><span class="s">&#39;pong </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">i</span><span class="p">)</span>
+
+        <span class="c"># We’ll stop the loop after 5 pings</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">i</span> <span class="o">==</span> <span class="mi">5</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">stream</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
+</pre></div>
+<p>This even adds more boilerplate code, but it will pay of if you use more
+sockets and most of that stuff in <em>run()</em> can be put into a base class. Another
+drawback is, that the IOLoop only uses <a class="reference external" href="http://zeromq.github.com/pyzmq/api/generated/zmq.core.socket.html#zmq.core.socket.Socket.recv_multipart">recv_multipart()</a>.
+So you always get a lists of byte strings which you have to decode or
+deserialize on your own. However, you can use all the <em>send</em> methods socket
+offers (like <em>send_unicode()</em> or <em>send_json()</em>). You can also stop the loop
+from within a message handler.</p>
+<p>In the next sections, I’ll discuss how you could implement a PyZMQ process that
+uses the event loop.</p>
+</div>
+<div class="section" id="communication-design">
+<h1>Communication Design</h1>
+<p>Before you start to implement anything, you should think about what kind of
+processes you need in your application and which messages they exchange. You
+should also decide what kind of message format and serialization you want to
+use.</p>
+<p>PyZMQ has built-in support for Unicode (<em>send</em> sends plain C strings which map
+to Python <em>byte</em> objects, so there’s a separate method to send Unicode
+strings), JSON and Pickle.</p>
+<p>JSON is nice, because it’s fast and lets you integrate processes written in
+other languages into you application. It’s also a bit safer, because you cannot
+receive arbitrary objects as with <a class="reference external" href="http://docs.python.org/py3k/library/pickle#restricting-globals">pickle</a>.  The most
+straightforward syntax for JSON messages is to let them be triples <em>[msg_type,
+args, kwargs]</em>, where <em>msg_type</em> maps to a method name and <em>args</em> and <em>kwargs</em>
+get passed as positional and keyword arguments.</p>
+<p>I strongly recommend you to document each chain of messages your application
+sends to perform a certain task. I do this with fancy PowerPoint graphics and
+with even fancier ASCII art in <a class="reference external" href="http://sphinx.pocoo.org">Sphinx</a>. Here is how
+I would document our ping-pong:</p>
+<div class="highlight"><pre><span class="gh">Sending pings</span>
+<span class="gh">-------------</span>
+
+<span class="m">*</span> If the ping process sends a <span class="ge">*ping*</span>, the pong processes responds with a
+  <span class="ge">*pong*</span>.
+<span class="m">*</span> The number of pings (and pongs) is counted. The current ping count is
+  sent with each message.
+
+<span class="se">::</span>
+
+<span class="s">    PingProc      PongProc</span>
+<span class="s">     [REQ] ---1--&gt; [REP]</span>
+<span class="s">           &lt;--2---</span>
+
+
+<span class="s">    1 IN : [&#39;ping, count&#39;]</span>
+<span class="s">    1 OUT: [&#39;ping, count&#39;]</span>
+
+<span class="s">    2 IN : [&#39;pong, count&#39;]</span>
+<span class="s">    2 OUT: [&#39;pong, count&#39;]</span>
+</pre></div>
+<p>First, I write some bullet points that explain how the processes behave and why
+they behave this way. This is followed by some kind of sequence diagram that
+shows when which process sents which message using which socket type. Finally,
+I write down how the messages are looking. <tt class="docutils literal"># IN</tt> is what you would pass to
+<em>send_multipart</em> and <tt class="docutils literal"># OUT</tt> is, what is received on the other side by
+<em>recv_multipart</em>. If one of the participating sockets is a <em>ROUTER</em> or
+<em>DEALER</em>, <em>IN</em> and <em>OUT</em> will differ (though that’s not the case in this
+example). Everything in single quotation marks (<tt class="docutils literal">'</tt>) represents a JSON
+serialized list.</p>
+<p>If our pong process used a <em>ROUTER</em> socket instead of the <em>REP</em> socket, it
+would look like this:</p>
+<pre class="literal-block">
+1 IN : ['ping, count']
+1 OUT: [ping_uuid, '', 'ping, count']
+
+2 IN : [ping_uuid, '', 'pong, count']
+2 OUT: ['pong, count']
+</pre>
+<p>This seems like a lot of tedious work, but trust me, it really helps a lot
+when you need to change something a few weeks later!</p>
+</div>
+<div class="section" id="application-design">
+<h1>Application Design</h1>
+<p>In the examples above, the <em>Pong</em> process was responsible for setting
+everything up, for receiving/sending messages and for the actual application
+logic (counting incoming pings and creating a pong).</p>
+<p>Obviously, this is not a very good design. What we can do about this is to put
+most of that nasty setup stuff into a base class which all your processes can
+inherit from, and to put all the actual application logic into a separate
+(PyZMQ independent) class.</p>
+<div class="section" id="zmqpocess-the-base-class-for-all-processes">
+<h2>ZmqPocess – The Base Class for all Processes</h2>
+<p>The base class basically implements two things:</p>
+<ul class="simple">
+<li>a <em>setup</em> method that creates a context an a loop</li>
+<li>a <em>stream</em> factory method for streams with a <em>on_recv</em> callback. It creates
+a socket and can connect/bind it to a given address or bind it to a random
+port (that’s why it returns the port number in addition to the stream
+itself).</li>
+</ul>
+<p>It also inherits <a class="reference external" href="http://docs.python.org/py3k/library/multiprocessing#process-and-exceptions">multiprocessing.Process</a>
+so that it is easier to spawn it as sub-process. Of course, you can also just
+call its <em>run()</em> method from you <em>main()</em>.</p>
+<div class="highlight"><pre><span class="c"># zmqproc.py</span>
+<span class="kn">import</span> <span class="nn">multiprocessing</span>
+
+<span class="kn">from</span> <span class="nn">zmq.eventloop</span> <span class="kn">import</span> <span class="n">ioloop</span><span class="p">,</span> <span class="n">zmqstream</span>
+<span class="kn">import</span> <span class="nn">zmq</span>
+
+
+<span class="k">class</span> <span class="nc">ZmqProcess</span><span class="p">(</span><span class="n">multiprocessing</span><span class="o">.</span><span class="n">Process</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">    This is the base for all processes and offers utility functions</span>
+<span class="sd">    for setup and creating new streams.</span>
+
+<span class="sd">    &quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span>
+
+        <span class="bp">self</span><span class="o">.</span><span class="n">context</span> <span class="o">=</span> <span class="bp">None</span>
+        <span class="sd">&quot;&quot;&quot;The ØMQ :class:`~zmq.Context` instance.&quot;&quot;&quot;</span>
+
+        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span> <span class="o">=</span> <span class="bp">None</span>
+        <span class="sd">&quot;&quot;&quot;PyZMQ&#39;s event loop (:class:`~zmq.eventloop.ioloop.IOLoop`).&quot;&quot;&quot;</span>
+
+    <span class="k">def</span> <span class="nf">setup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">        Creates a :attr:`context` and an event :attr:`loop` for the process.</span>
+
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">context</span> <span class="o">=</span> <span class="n">zmq</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">loop</span> <span class="o">=</span> <span class="n">ioloop</span><span class="o">.</span><span class="n">IOLoop</span><span class="o">.</span><span class="n">instance</span><span class="p">()</span>
+
+    <span class="k">def</span> <span class="nf">stream</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sock_type</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="n">bind</span><span class="p">,</span> <span class="n">callback</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">subscribe</span><span class="o">=</span><span class="n">b</span><span class="s">&#39;&#39;</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">        Creates a :class:`~zmq.eventloop.zmqstream.ZMQStream`.</span>
+
+<span class="sd">        :param sock_type: The ØMQ socket type (e.g. ``zmq.REQ``)</span>
+<span class="sd">        :param addr: Address to bind or connect to formatted as *host:port*,</span>
+<span class="sd">                *(host, port)* or *host* (bind to random port).</span>
+<span class="sd">                If *bind* is ``True``, *host* may be:</span>
+
+<span class="sd">                - the wild-card ``*``, meaning all available interfaces,</span>
+<span class="sd">                - the primary IPv4 address assigned to the interface, in its</span>
+<span class="sd">                  numeric representation or</span>
+<span class="sd">                - the interface name as defined by the operating system.</span>
+
+<span class="sd">                If *bind* is ``False``, *host* may be:</span>
+
+<span class="sd">                - the DNS name of the peer or</span>
+<span class="sd">                - the IPv4 address of the peer, in its numeric representation.</span>
+
+<span class="sd">                If *addr* is just a host name without a port and *bind* is</span>
+<span class="sd">                ``True``, the socket will be bound to a random port.</span>
+<span class="sd">        :param bind: Binds to *addr* if ``True`` or tries to connect to it</span>
+<span class="sd">                otherwise.</span>
+<span class="sd">        :param callback: A callback for</span>
+<span class="sd">                :meth:`~zmq.eventloop.zmqstream.ZMQStream.on_recv`, optional</span>
+<span class="sd">        :param subscribe: Subscription pattern for *SUB* sockets, optional,</span>
+<span class="sd">                defaults to ``b&#39;&#39;``.</span>
+<span class="sd">        :returns: A tuple containg the stream and the port number.</span>
+
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="n">sock</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">sock_type</span><span class="p">)</span>
+
+        <span class="c"># addr may be &#39;host:port&#39; or (&#39;host&#39;, port)</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
+            <span class="n">addr</span> <span class="o">=</span> <span class="n">addr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;:&#39;</span><span class="p">)</span>
+        <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">addr</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="k">else</span> <span class="p">(</span><span class="n">addr</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="bp">None</span><span class="p">)</span>
+
+        <span class="c"># Bind/connect the socket</span>
+        <span class="k">if</span> <span class="n">bind</span><span class="p">:</span>
+            <span class="k">if</span> <span class="n">port</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="s">&#39;tcp://</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
+            <span class="k">else</span><span class="p">:</span>
+                <span class="n">port</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">bind_to_random_port</span><span class="p">(</span><span class="s">&#39;tcp://</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">host</span><span class="p">)</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;tcp://</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
+
+        <span class="c"># Add a default subscription for SUB sockets</span>
+        <span class="k">if</span> <span class="n">sock_type</span> <span class="o">==</span> <span class="n">zmq</span><span class="o">.</span><span class="n">SUB</span><span class="p">:</span>
+            <span class="n">sock</span><span class="o">.</span><span class="n">setsockopt</span><span class="p">(</span><span class="n">zmq</span><span class="o">.</span><span class="n">SUBSCRIBE</span><span class="p">,</span> <span class="n">subscribe</span><span class="p">)</span>
+
+        <span class="c"># Create the stream and add the callback</span>
+        <span class="n">stream</span> <span class="o">=</span> <span class="n">zmqstream</span><span class="o">.</span><span class="n">ZMQStream</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">callback</span><span class="p">:</span>
+            <span class="n">stream</span><span class="o">.</span><span class="n">on_recv</span><span class="p">(</span><span class="n">callback</span><span class="p">)</span>
+
+        <span class="k">return</span> <span class="n">stream</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</span><span class="p">)</span>
+</pre></div>