<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-5440028356946346379</id><updated>2009-07-11T11:12:34.739-04:00</updated><title type='text'>Doug Hellmann</title><subtitle type='html'>&lt;p&gt;Code Interstices&lt;/p&gt;

&lt;p&gt;All the little things that happen between bouts of coding.  Covering internet technologies, Python, Mac OS X, and open source.&lt;/p&gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default?start-index=26&amp;max-results=25'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>331</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-1835715432958838692</id><published>2009-07-06T08:05:00.001-04:00</published><updated>2009-07-06T08:05:28.362-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>Book Review: IronPython in Action</title><content type='html'>&lt;iframe src="http://rcm.amazon.com/e/cm?t=hellflynet-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=1933988339&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;float:left;margin-right:1em;margin-bottom:1em;" scrolling="no" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;IronPython in Action&lt;/strong&gt; by Michael Foord and Christian Muirhead covers the version of Python built to run on Microsoft's CLR and explains how to use it with the .NET framework.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Disclaimer: I received a review copy of this book from Manning through the PyATL Book Club.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;There are two target audiences for this book: experienced Python developers wanting to learn .NET, and experienced .NET developers wanting to learn Python.  Both groups will find plenty of interesting material and learn a lot.  After some relatively basic introductory chapters, the authors dig right in building a complex GUI application, and then implementing a web interface for the same desktop application.  &lt;br /&gt;&lt;br /&gt;Along the way they introduce topics such as different programming models in Python, navigating the MSDN documentation (very important for understanding the scope of features available in .NET), packaging your app for distribution under Windows, data persistence, XML parsing, design patterns, automated testing, system administration, relational databases, and &lt;em&gt;two separate&lt;/em&gt; GUI libraries.  &lt;br /&gt;&lt;br /&gt;All of the code is clear, concise, and useful -- there are no fluffy, throw-away code snippets that fall short in the real world.  While many of the examples given are specific to IronPython or .NET, the techniques being illustrated are definitely not.&lt;br /&gt;&lt;br /&gt;I recommend this book for any Windows developer interested in learning about Python, and for Python developers looking into deploying an application under Windows.  If you don't fall into either of those groups, I can still recommend that you pick up a copy for some excellent advice on general programming topics and the solid example code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-1835715432958838692?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/1835715432958838692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=1835715432958838692' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/1835715432958838692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/1835715432958838692'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/07/book-review-ironpython-in-action.html' title='Book Review: IronPython in Action'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-3102098936979012700</id><published>2009-07-05T09:30:00.001-04:00</published><updated>2009-07-05T09:30:20.015-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>New command line interface to PyMOTW</title><content type='html'>The &lt;a href="http://www.doughellmann.com/projects/PyMOTW/"&gt;1.95 release of PyMOTW&lt;/a&gt; includes a command line interface to access the documentation for a module.  &lt;br /&gt;&lt;br /&gt;The package can be installed via easy_install or pip:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;$ pip install PyMOTW&lt;br /&gt;Downloading/unpacking PyMOTW&lt;br /&gt;  Downloading PyMOTW-1.95.tar.gz (2.2Mb): 2.2Mb downloaded&lt;br /&gt;  Running setup.py egg_info for package PyMOTW&lt;br /&gt;    warning: no files found matching 'ChangeLog'&lt;br /&gt;    warning: no files found matching '*.py' under directory 'sphinx/templates'&lt;br /&gt;    no previously-included directories found matching 'utils'&lt;br /&gt;Installing collected packages: PyMOTW&lt;br /&gt;  Running setup.py install for PyMOTW&lt;br /&gt;    changing mode of build/scripts-2.6/motw from 644 to 755&lt;br /&gt;    warning: no files found matching 'ChangeLog'&lt;br /&gt;    warning: no files found matching '*.py' under directory 'sphinx/templates'&lt;br /&gt;    no previously-included directories found matching 'utils'&lt;br /&gt;    changing mode of /Users/dhellmann/.virtualenvs/testpymotw/bin/motw to 755&lt;br /&gt;Successfully installed PyMOTW&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and then to use the command line interface, run &lt;code&gt;motw&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;$ motw -h&lt;br /&gt;Usage: motw [options] &lt;module_name&gt;&lt;br /&gt;&lt;br /&gt;Options:&lt;br /&gt;  -h, --help  show this help message and exit&lt;br /&gt;  -t, --text  Print plain-text version of help to stdout&lt;br /&gt;  -w, --web   Open HTML version of help from web&lt;br /&gt;  --html      Open HTML version of help from installed file&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;For example, &lt;code&gt;motw abc&lt;/code&gt; opens the local version of &lt;a href="http://blog.doughellmann.com/2009/07/pymotw-abc-abstract-base-classes.html"&gt;this week's article&lt;/a&gt;.  You can also use the "-w" option to go to my web site instead of reading the local version, so you always have the latest version of an article.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-3102098936979012700?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/3102098936979012700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=3102098936979012700' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3102098936979012700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3102098936979012700'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/07/new-command-line-interface-to-pymotw.html' title='New command line interface to PyMOTW'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-257613817223471603</id><published>2009-07-05T09:18:00.001-04:00</published><updated>2009-07-05T09:18:48.519-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>PyMOTW: abc - Abstract Base Classes</title><content type='html'>&lt;div class="section" id="module-abc"&gt;&lt;h1&gt;abc &amp;#8211; Abstract Base Classes&lt;/h1&gt;&lt;table class="docutils field-list" frame="void" rules="none"&gt;&lt;col class="field-name"&gt;&lt;/col&gt;&lt;col class="field-body"&gt;&lt;/col&gt;&lt;tbody valign="top"&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Purpose:&lt;/th&gt;&lt;td class="field-body"&gt;Define and use abstract base classes for API checks in your code.&lt;/td&gt;&lt;/tr&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Python Version:&lt;/th&gt;&lt;td class="field-body"&gt;2.6&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="section" id="why-use-abstract-base-classes"&gt;&lt;br /&gt;&lt;h2&gt;Why use Abstract Base Classes?&lt;/h2&gt;&lt;p&gt;Abstract base classes are a form of interface checking more strict than individual &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;hasattr()&lt;/span&gt;&lt;/tt&gt; checks for particular methods.  By defining an abstract base class, you can define a common API for a set of subclasses.  This capability is especially useful in situations where a third-party is going to provide implementations, such as with plugins to an application, but can also aid you when working on a large team or with a large code-base where keeping all classes in your head at the same time is difficult or not possible.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="how-abcs-work"&gt;&lt;h2&gt;How ABCs Work&lt;/h2&gt;&lt;p&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;abc&lt;/span&gt;&lt;/tt&gt; works by marking methods of the base class as abstract, and then registering concrete classes as implementations of the abstract base.  If your code requires a particular API, you can use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;issubclass()&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;isinstance()&lt;/span&gt;&lt;/tt&gt; to check an object against the abstract class.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s start by defining an abstract base class to represent the API of a set of plugins for saving and loading data.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractmethod&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Retrieve data from the input source and return an object.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractmethod&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Save the data object to the output.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="registering-a-concrete-class"&gt;&lt;h2&gt;Registering a Concrete Class&lt;/h2&gt;&lt;p&gt;There are two ways to indicate that a concrete class implements an abstract: register the class with the abc or subclass directly from the abc.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;abc_base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegisteredImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RegisteredImplementation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Subclass:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;issubclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RegisteredImplementation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Instance:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RegisteredImplementation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In this example the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PluginImplementation&lt;/span&gt;&lt;/tt&gt; is not derived from &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PluginBase&lt;/span&gt;&lt;/tt&gt;, but is registered as implementing the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PluginBase&lt;/span&gt;&lt;/tt&gt; API.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_register.py&lt;br /&gt;Subclass: True&lt;br /&gt;Instance: True&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="implementation-through-subclassing"&gt;&lt;h2&gt;Implementation Through Subclassing&lt;/h2&gt;&lt;p&gt;By subclassing directly from the base, we can avoid the need to register the class explicitly.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;abc_base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SubclassImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Subclass:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;issubclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SubclassImplementation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Instance:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SubclassImplementation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In this case the normal Python class management is used to recognize &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PluginImplementation&lt;/span&gt;&lt;/tt&gt; as implementing the abstract &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PluginBase&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_subclass.py&lt;br /&gt;Subclass: True&lt;br /&gt;Instance: True&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;A side-effect of using direct subclassing is it is possible to find all of the implementations of your plugin by asking the base class for the list of known classes derived from it (this is not an abc feature, all classes can do this).&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;abc_base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc_subclass&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc_register&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__subclasses__&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;sc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Notice that even though &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;abc_register&lt;/span&gt;&lt;/tt&gt; is imported, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;RegisteredImplementation&lt;/span&gt;&lt;/tt&gt; is not among the list of subclasses because it is not actually derived from the base.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_find_subclasses.py&lt;br /&gt;SubclassImplementation&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Dr. Andr√© Roberge &lt;a class="reference external" href="http://us.pycon.org/2009/conference/schedule/event/47/"&gt;has described&lt;/a&gt; using this capability to discover plugins by importing all of the modules in a directory dynamically and then looking at the subclass list to find the implementation classes.&lt;/p&gt;&lt;div class="section" id="incomplete-implementations"&gt;&lt;h3&gt;Incomplete Implementations&lt;/h3&gt;&lt;p&gt;Another benefit of subclassing directly from your abstract base class is that the subclass cannot be instantiated unless it fully implements the abstract portion of the API.  This can keep half-baked implementations from triggering unexpected errors at runtime.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;abc_base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IncompleteImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IncompleteImplementation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Subclass:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;issubclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IncompleteImplementation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Instance:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IncompleteImplementation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_incomplete.py&lt;br /&gt;Subclass: True&lt;br /&gt;Instance:&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "abc_incomplete.py", line 22, in &amp;lt;module&amp;gt;&lt;br /&gt;    print 'Instance:', isinstance(IncompleteImplementation(), PluginBase)&lt;br /&gt;TypeError: Can't instantiate abstract class IncompleteImplementation with abstract methods load&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="concrete-methods-in-abcs"&gt;&lt;h2&gt;Concrete Methods in ABCs&lt;/h2&gt;&lt;p&gt;Although a concrete class must provide an implementation of an abstract methods, the abstract base class can also provide an implementation that can be invoked via &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;super()&lt;/span&gt;&lt;/tt&gt;.  This lets you re-use common logic by placing it in the base class, but force subclasses to provide an overriding method with (potentially) custom logic.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cStringIO&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StringIO&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ABCWithConcreteImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractmethod&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;base class reading data&amp;#39;&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConcreteOverride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ABCWithConcreteImplementation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;base_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ConcreteOverride&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retrieve_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;subclass sorting data&amp;#39;&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="nb"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StringIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;line one&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;line two&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;line three&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConcreteOverride&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retrieve_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Since &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ABCWithConcreteImplementation&lt;/span&gt;&lt;/tt&gt; is an abstract base class, it isn&amp;#8217;t possible to instantiate it to use it directly.  Subclasses &lt;em&gt;must&lt;/em&gt; provide an override for &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;retrieve_values()&lt;/span&gt;&lt;/tt&gt;, and in this case the concrete class massages the data before returning it at all.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_concrete_method.py&lt;br /&gt;base class reading data&lt;br /&gt;subclass sorting data&lt;br /&gt;['line one', 'line three', 'line two']&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="abstract-properties"&gt;&lt;h2&gt;Abstract Properties&lt;/h2&gt;&lt;p&gt;If your API specification includes attributes in addition to methods, you can require the attributes in concrete classes by defining them with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;#64;abstractproperty&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractproperty&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Should never get here&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@property&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;concrete property&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Base.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Implementation.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Base&lt;/span&gt;&lt;/tt&gt; class in the example cannot be instantiated because it has only an abstract version of the property getter method.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_abstractproperty.py&lt;br /&gt;ERROR: Can't instantiate abstract class Base with abstract methods value&lt;br /&gt;Implementation.value: concrete property&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;You can also define abstract read/write properties.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_getter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Should never see this&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractproperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value_getter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PartialImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractproperty&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Read-only&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Default value&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_getter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value_getter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Base.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PartialImplementation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;PartialImplementation.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Implementation.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;New value&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Changed value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Notice that the concrete property must be defined the same way as the abstract property.  Trying to override a read/write property in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PartialImplementation&lt;/span&gt;&lt;/tt&gt; with one that is read-only does not work.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_abstractproperty_rw.py&lt;br /&gt;ERROR: Can't instantiate abstract class Base with abstract methods value&lt;br /&gt;ERROR: Can't instantiate abstract class PartialImplementation with abstract methods value&lt;br /&gt;Implementation.value: Default value&lt;br /&gt;Changed value: New value&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, the decorator syntax does not work for read/write abstract properties the way it does with concrete properties.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractproperty&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Should never see this&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setter&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Default value&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@property&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="nd"&gt;@value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setter&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Implementation.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;New value&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Changed value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Notice that the caller cannot set the property value.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_abstractproperty_rw_deco.py&lt;br /&gt;Implementation.value: Default value&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "abc_abstractproperty_rw_deco.py", line 40, in &amp;lt;module&amp;gt;&lt;br /&gt;    i.value = 'New value'&lt;br /&gt;AttributeError: can't set attribute&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="collection-types"&gt;&lt;h2&gt;Collection Types&lt;/h2&gt;&lt;p&gt;The &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;collections&lt;/span&gt;&lt;/tt&gt; module defines several abstract base classes related to container (and containable) types.&lt;/p&gt;&lt;p&gt;General container classes:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;Container&lt;/li&gt;&lt;li&gt;Sized&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Iterator and Sequence classes:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;Iterable&lt;/li&gt;&lt;li&gt;Iterator&lt;/li&gt;&lt;li&gt;Sequence&lt;/li&gt;&lt;li&gt;MutableSequence&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Unique values:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;Hashable&lt;/li&gt;&lt;li&gt;Set&lt;/li&gt;&lt;li&gt;MutableSet&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Mappings:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;Mapping&lt;/li&gt;&lt;li&gt;MutableMapping&lt;/li&gt;&lt;li&gt;MappingView&lt;/li&gt;&lt;li&gt;KeysView&lt;/li&gt;&lt;li&gt;ItemsView&lt;/li&gt;&lt;li&gt;ValuesView&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Miscelaneous:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;Callable&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In addition to serving as detailed real-world examples of abstract base classes, Python&amp;#8217;s built-in types are automatically registered to these classes when you import &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;collections&lt;/span&gt;&lt;/tt&gt;. This means you can safely use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;isinstance()&lt;/span&gt;&lt;/tt&gt; to check parameters in your code to ensure that they support the API you need.  The base classes can also be used to define your own collection types, since many of them provide concrete implementations of the internals and only need a few methods overridden.  Refer to the standard library docs for collections for more details.&lt;/p&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/abc.html"&gt;abc&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for this module.&lt;/dd&gt;&lt;dt&gt;&lt;span class="target" id="index-0"&gt;&lt;/span&gt;&lt;a class="reference external" href="http://www.python.org/dev/peps/pep-3119"&gt;&lt;strong&gt;PEP 3119&lt;/strong&gt;&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;Introducing Abstract Base Classes&lt;/dd&gt;&lt;dt&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;collections&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;The collections module includes abstract base classes for several collection types.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/collections.html"&gt;collections&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for collections.&lt;/dd&gt;&lt;dt&gt;&lt;span class="target" id="index-1"&gt;&lt;/span&gt;&lt;a class="reference external" href="http://www.python.org/dev/peps/pep-3141"&gt;&lt;strong&gt;PEP 3141&lt;/strong&gt;&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;A Type Hierarchy for Numbers&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://en.wikipedia.org/wiki/Strategy_pattern"&gt;Wikipedia: Strategy Pattern&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;Description and examples of the strategy pattern.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://us.pycon.org/2009/conference/schedule/event/47/"&gt;Plugins and monkeypatching&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;PyCon 2009 presentation by Dr. Andr√© Roberge&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The &lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/abc/"&gt;canonical version&lt;/a&gt; of this article&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-257613817223471603?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/257613817223471603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=257613817223471603' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/257613817223471603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/257613817223471603'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/07/pymotw-abc-abstract-base-classes.html' title='PyMOTW: abc - Abstract Base Classes'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-6328402425119681605</id><published>2009-07-04T18:45:00.001-04:00</published><updated>2009-07-04T18:45:04.932-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='PyATL'/><title type='text'>Book Review: Hello, World!</title><content type='html'>&lt;iframe src="http://rcm.amazon.com/e/cm?t=hellflynet-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=1933988495&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;float:right;margin-left:1em;margin-bottom:1em;" scrolling="no" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Hello, World! Computer Programming for Kids and Other Beginners&lt;/strong&gt; by Warren and Carter Sande is an introduction to programming in general (and Python specifically) aimed at pre-teens or young teens.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Disclaimer: I received a review copy of this book from Manning through the PyATL Book Club.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Although the book is designed for a young audience, it is not condescending as many kids books tend to be so it remains readable by adults who need a very basic text on how computer programs work.  And by "basic" I mean from the ground up.  The book covers using an editor to create and modify program files, numbers, strings, variables, branching, and looping.  It doesn't stop with basic topics, though.  By the mid-point of the book, the authors have built up to the point where introducing PyGame and graphics programming isn't a stretch, and by the end of the book they have covered the GUI, animation, and sound techniques needed to create &lt;em&gt;two&lt;/em&gt; simple computer games.&lt;br /&gt;&lt;br /&gt;The writing style is clear and friendly without coming off as cutesy.  Each chapter is relatively short, with review questions at the end in the style of a text book (the answer guide is available in the appendix).  There is a liberal use of sidebars to break up longer sections or highlight related digressions.  And the authors also don't shy away from showing "broken" versions of programs as they evolve, which teaches the reader how to understand error messages and debug problems -- an extremely important skill for a programmer.&lt;br /&gt;&lt;br /&gt;I recommend checking out &lt;strong&gt;Hello, World!&lt;/strong&gt; if you have a young person in your life who is interested in learning about programming.  Writing the book was a &lt;a href="http://watch.ctv.ca/news/clip186877#clip186877"&gt;father/son project&lt;/a&gt;, and reading it together seems like a fun parent/child activity for the summer.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-6328402425119681605?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/6328402425119681605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=6328402425119681605' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6328402425119681605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6328402425119681605'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/07/book-review-hello-world.html' title='Book Review: Hello, World!'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-7434505190000613264</id><published>2009-06-28T09:02:00.001-04:00</published><updated>2009-06-28T09:02:01.562-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>PyMOTW: pyclbr</title><content type='html'>&lt;div class="section" id="module-pyclbr"&gt;&lt;h1&gt;pyclbr &amp;#8211; Python class browser support&lt;/h1&gt;&lt;table class="docutils field-list" frame="void" rules="none"&gt;&lt;col class="field-name"&gt;&lt;/col&gt;&lt;col class="field-body"&gt;&lt;/col&gt;&lt;tbody valign="top"&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Purpose:&lt;/th&gt;&lt;td class="field-body"&gt;Implements an API suitable for use in a source code editor for making a class browser.&lt;/td&gt;&lt;/tr&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Python Version:&lt;/th&gt;&lt;td class="field-body"&gt;1.4 and later&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;pyclbr&lt;/span&gt;&lt;/tt&gt; can scan Python source to find classes and stand-alone functions.  The information about class, method, and function names and line numbers is gathered using &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;tokenize&lt;/span&gt;&lt;/tt&gt; &lt;em&gt;without&lt;/em&gt; importing the code.&lt;/p&gt;&lt;p&gt;The examples below use this source file as input:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Example source for pyclbr.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;This is the base class.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sub1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;This is the first subclass.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sub2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;This is the second subclass.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Mixin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;A mixin class.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MixinUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sub2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Mixin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Overrides method1 and method2&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;method3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Stand-alone function.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="scanning-for-classes"&gt;&lt;br /&gt;&lt;h2&gt;Scanning for Classes&lt;/h2&gt;&lt;p&gt;There are two public functions exposed by &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;pyclbr&lt;/span&gt;&lt;/tt&gt;.  &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;readmodule()&lt;/span&gt;&lt;/tt&gt; takes the name of the module as argument returns a mapping of class names to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Class&lt;/span&gt;&lt;/tt&gt; objects containing the meta-data about the class source.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pyclbr&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;operator&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;itemgetter&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Class:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;File: {0} [{1}]&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;class_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;class_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lineno&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;show_super_classes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;show_methods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_methods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;class_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lineno&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;class_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;itemgetter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Method: {0} [{1}]&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lineno&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_super_classes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;super_class_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;super_class&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;class_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;super&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;super_class&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;object&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;continue&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;super_class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;basestring&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;super_class_names&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;super_class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;super_class_names&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;super_class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;super_class_names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;Super classes:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;super_class_names&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;example_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyclbr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readmodule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;pyclbr_example&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_data&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lineno&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;show_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The meta-data for the class includes the file and line number where it is defined, as well as the names of super classes.  The methods of the class are saved as a mapping between method name and line number.  The output below shows the classes and methods listed in order based on their line number in the source file.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python pyclbr_readmodule.py&lt;br /&gt;Class: Base&lt;br /&gt;        File: pyclbr_example.py [10]&lt;br /&gt;        Method: method1 [14]&lt;br /&gt;&lt;br /&gt;Class: Sub1&lt;br /&gt;        File: pyclbr_example.py [17]&lt;br /&gt;        Super classes: ['Base']&lt;br /&gt;&lt;br /&gt;Class: Sub2&lt;br /&gt;        File: pyclbr_example.py [21]&lt;br /&gt;        Super classes: ['Base']&lt;br /&gt;&lt;br /&gt;Class: Mixin&lt;br /&gt;        File: pyclbr_example.py [25]&lt;br /&gt;        Method: method2 [29]&lt;br /&gt;&lt;br /&gt;Class: MixinUser&lt;br /&gt;        File: pyclbr_example.py [32]&lt;br /&gt;        Super classes: ['Sub2', 'Mixin']&lt;br /&gt;        Method: method1 [36]&lt;br /&gt;        Method: method2 [39]&lt;br /&gt;        Method: method3 [42]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="scanning-for-functions"&gt;&lt;h2&gt;Scanning for Functions&lt;/h2&gt;&lt;p&gt;The other public function in &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;pyclbr&lt;/span&gt;&lt;/tt&gt; is &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;readmodule_ex()&lt;/span&gt;&lt;/tt&gt;.  It does everything that &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;readmodule()&lt;/span&gt;&lt;/tt&gt; does, and adds functions to the result set.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pyclbr&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;operator&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;itemgetter&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;example_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyclbr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readmodule_ex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;pyclbr_example&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lineno&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pyclbr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Function: {0} [{1}]&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lineno&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Each &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Function&lt;/span&gt;&lt;/tt&gt; object has properties much like the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Class&lt;/span&gt;&lt;/tt&gt; object.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python pyclbr_readmodule_ex.py&lt;br /&gt;Function: my_function [45]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/pyclbr.html"&gt;pyclbr&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for this module.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;inspect&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;The inspect module can discover more meta-data about classes and functions, but requires importing the code.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;tokenize&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;The tokenize module parses Python source code into tokens.&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The &lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/pyclbr/"&gt;canonical version&lt;/a&gt; of this article&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-7434505190000613264?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/7434505190000613264/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=7434505190000613264' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/7434505190000613264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/7434505190000613264'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/06/pymotw-pyclbr.html' title='PyMOTW: pyclbr'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-3283799661588098406</id><published>2009-06-21T10:59:00.001-04:00</published><updated>2009-06-21T11:13:14.361-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>PyMOTW: robotparser</title><content type='html'>&lt;div class="section" id="module-robotparser"&gt;&lt;br /&gt;&lt;h1&gt;robotparser &amp;#8211; Internet spider access control&lt;/h1&gt;&lt;table class="docutils field-list" frame="void" rules="none"&gt;&lt;col class="field-name"&gt;&lt;/col&gt;&lt;col class="field-body"&gt;&lt;/col&gt;&lt;tbody valign="top"&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Purpose:&lt;/th&gt;&lt;td class="field-body"&gt;Parse robots.txt file used to control Internet spiders&lt;/td&gt;&lt;/tr&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Python Version:&lt;/th&gt;&lt;td class="field-body"&gt;2.1.3 and later&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;robotparser&lt;/span&gt;&lt;/tt&gt; implements a parser for the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;robots.txt&lt;/span&gt;&lt;/tt&gt; file format, including a simple function for checking if a given user agent can access a resource.  It is intended for use in well-behaved spiders or other crawler applications that need to either be throttled or otherwise restricted.&lt;/p&gt;&lt;div class="admonition note"&gt;&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;&lt;p class="last"&gt;The &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;robotparser&lt;/span&gt;&lt;/tt&gt; module has been renamed &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;urllib.robotparser&lt;/span&gt;&lt;/tt&gt; in Python 3.0.&lt;br /&gt;Existing code using &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;robotparser&lt;/span&gt;&lt;/tt&gt; can be updated using 2to3.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="robots-txt"&gt;&lt;h2&gt;robots.txt&lt;/h2&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;robots.txt&lt;/span&gt;&lt;/tt&gt; file format is a simple text-based access control system for computer programs that automatically access web resources (&amp;#8220;spiders&amp;#8221;, &amp;#8220;crawlers&amp;#8221;, etc.).  The file is made up of records that specify the user agent identifier for the program followed by a list of URLs (or URL prefixes) the agent may not access.&lt;/p&gt;&lt;p&gt;This is the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;robots.txt&lt;/span&gt;&lt;/tt&gt; file for &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;http://www.doughellmann.com/&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;User-agent: *&lt;br /&gt;Disallow: /admin/&lt;br /&gt;Disallow: /downloads/&lt;br /&gt;Disallow: /media/&lt;br /&gt;Disallow: /static/&lt;br /&gt;Disallow: /codehosting/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;It prevents access to some of the expensive parts of my site that would overload the server if a search engine tried to index them.  For a more complete set of examples, refer to &lt;a class="reference external" href="http://www.robotstxt.org/orig.html"&gt;The Web Robots Page&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="simple-example"&gt;&lt;h2&gt;Simple Example&lt;/h2&gt;&lt;p&gt;Using the data above, a simple crawler can test whether it is allowed to download a page using the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;RobotFileParser&lt;/span&gt;&lt;/tt&gt;&amp;#8216;s &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;can_fetch()&lt;/span&gt;&lt;/tt&gt; method.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;robotparser&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;urlparse&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;AGENT_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;PyMOTW&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;URL_BASE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;http://www.doughellmann.com/&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;robotparser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RobotFileParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urlparse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urljoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL_BASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;robots.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;PATHS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class="s"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="s"&gt;&amp;#39;/PyMOTW/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="s"&gt;&amp;#39;/admin/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="s"&gt;&amp;#39;/downloads/PyMOTW-1.92.tar.gz&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;PATHS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%6s&lt;/span&gt;&lt;span class="s"&gt; : &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can_fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AGENT_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urlparse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urljoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL_BASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%6s&lt;/span&gt;&lt;span class="s"&gt; : &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can_fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AGENT_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The URL argument to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;can_fetch()&lt;/span&gt;&lt;/tt&gt; can be a path relative to the root of the site, or full URL.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python robotparser_simple.py&lt;br /&gt;  True : /&lt;br /&gt;  True : http://www.doughellmann.com/&lt;br /&gt;&lt;br /&gt;  True : /PyMOTW/&lt;br /&gt;  True : http://www.doughellmann.com/PyMOTW/&lt;br /&gt;&lt;br /&gt; False : /admin/&lt;br /&gt; False : http://www.doughellmann.com/admin/&lt;br /&gt;&lt;br /&gt; False : /downloads/PyMOTW-1.92.tar.gz&lt;br /&gt; False : http://www.doughellmann.com/downloads/PyMOTW-1.92.tar.gz&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="long-lived-spiders"&gt;&lt;h2&gt;Long-lived Spiders&lt;/h2&gt;&lt;p&gt;An application that takes a long time to process the resources it downloads or that is throttled to pause between downloads may want to check for new &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;robots.txt&lt;/span&gt;&lt;/tt&gt; files periodically based on the age of the content it has downloaded already.  The age is not managed automatically, but there are convenience methods to make tracking it easier.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;robotparser&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;urlparse&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;AGENT_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;PyMOTW&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;robotparser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RobotFileParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="c"&gt;# Using the local copy&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;robots.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modified&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;PATHS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class="s"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="s"&gt;&amp;#39;/PyMOTW/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="s"&gt;&amp;#39;/admin/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="s"&gt;&amp;#39;/downloads/PyMOTW-1.92.tar.gz&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PATHS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mtime&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;age:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;re-reading robots.txt&amp;#39;&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modified&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%6s&lt;/span&gt;&lt;span class="s"&gt; : &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;can_fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AGENT_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="c"&gt;# Simulate a delay in processing&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This extreme example downloads a new &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;robots.txt&lt;/span&gt;&lt;/tt&gt; file if the one it has is more than 1 second old.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python robotparser_longlived.py&lt;br /&gt;&lt;br /&gt;age: 0&lt;br /&gt;  True : /&lt;br /&gt;&lt;br /&gt;age: 1&lt;br /&gt;  True : /PyMOTW/&lt;br /&gt;&lt;br /&gt;age: 2 re-reading robots.txt&lt;br /&gt; False : /admin/&lt;br /&gt;&lt;br /&gt;age: 1&lt;br /&gt; False : /downloads/PyMOTW-1.92.tar.gz&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;A &amp;#8220;nicer&amp;#8221; version of the long-lived application might request the modification time for the file before downloading the entire thing.  On the other hand, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;robots.txt&lt;/span&gt;&lt;/tt&gt; files are usually fairly small, so it isn&amp;#8217;t that much more expensive to just grab the entire document again.&lt;/p&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/robotparser.html"&gt;robotparser&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for this module.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://www.robotstxt.org/orig.html"&gt;The Web Robots Page&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;Description of robots.txt format.&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The &lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/robotparser/"&gt;canonical version&lt;/a&gt; of this article&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-3283799661588098406?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/3283799661588098406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=3283799661588098406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3283799661588098406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3283799661588098406'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/06/pymotw-robotparser.html' title='PyMOTW: robotparser'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-6479712573275444008</id><published>2009-06-19T09:23:00.001-04:00</published><updated>2009-06-19T09:23:52.843-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Exception Handling Techniques</title><content type='html'>Last week when a colleague was reviewing some code I had written, he had a few questions about an unusual exception handling technique I was using.  I had been fixing a bug in which the cleanup code from one error was generating another error, and the second exception masked the first.  I went through a few contortions before I came up with a solution that allowed the cleanup code to fail but still preserved the original error and traceback for the user.&lt;br /&gt;&lt;br /&gt;After our conversation, I decided to write up a quick example to share.  I prefaced the description with some basic exception handling information to put it in context, and I posted the &lt;a href="http://www.doughellmann.com/articles/Python-Exception-Handling/index.html"&gt;resulting article on my site&lt;/a&gt;.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-6479712573275444008?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/6479712573275444008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=6479712573275444008' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6479712573275444008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6479712573275444008'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/06/exception-handling-techniques.html' title='Exception Handling Techniques'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-401767123904814065</id><published>2009-06-14T11:47:00.001-04:00</published><updated>2009-06-14T11:47:26.856-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>PyMOTW: gettext</title><content type='html'>&lt;div class="section" id="module-gettext"&gt;&lt;h1&gt;gettext &amp;#8211; Message Catalogs&lt;/h1&gt;&lt;table class="docutils field-list" frame="void" rules="none"&gt;&lt;col class="field-name"&gt;&lt;/col&gt;&lt;col class="field-body"&gt;&lt;/col&gt;&lt;tbody valign="top"&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Purpose:&lt;/th&gt;&lt;td class="field-body"&gt;Message catalog API for internationalization.&lt;/td&gt;&lt;/tr&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Python Version:&lt;/th&gt;&lt;td class="field-body"&gt;2.1.3 and later&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;The &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;gettext&lt;/span&gt;&lt;/tt&gt; module provides an all-Python implementation compatible with the GNU gettext library for message translation and catalog management.  The tools available with the Python source distribution enable you to extract messages from your source, build a message catalog containing translations, and use that message catalog to print an appropriate message for the user at runtime.&lt;/p&gt;&lt;p&gt;Message catalogs can be used to provide internationalized interfaces for your program, showing messages in a language appropriate to the user.  They can also be used for other message customizations, including &amp;#8220;skinning&amp;#8221; an interface for different wrappers or partners.&lt;/p&gt;&lt;div class="admonition note"&gt;&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;&lt;p class="last"&gt;Although the standard library documentation says everything you need is included with&lt;br /&gt;Python, I found that &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;pygettext.py&lt;/span&gt;&lt;/tt&gt; refused to extract messages wrapped in the&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ungettext&lt;/span&gt;&lt;/tt&gt; call, even when I used what seemed to be the appropriate command line&lt;br /&gt;options. I ended up installing the GNU gettext tools from source and using&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;xgettext&lt;/span&gt;&lt;/tt&gt; instead.  YMMV.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="translation-workflow-overview"&gt;&lt;h2&gt;Translation Workflow Overview&lt;/h2&gt;&lt;p&gt;The process for setting up and using translations includes five steps:&lt;/p&gt;&lt;ol class="arabic"&gt;&lt;li&gt;&lt;p class="first"&gt;Mark up literal strings in your code that contain messages to translate.&lt;/p&gt;&lt;p&gt;Start by identifying the messages within your program source that need to be translated,&lt;br /&gt;and marking the literal strings so the extraction program can find them.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="first"&gt;Extract the messages.&lt;/p&gt;&lt;p&gt;After you have identified the translatable strings in your program source, use&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;xgettext&lt;/span&gt;&lt;/tt&gt; to pull the strings out and create a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.pot&lt;/span&gt;&lt;/tt&gt; file, or translation&lt;br /&gt;template. The template is a text file with copies of all of the strings you identified&lt;br /&gt;and placeholders for their translations.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="first"&gt;Translate the messages.&lt;/p&gt;&lt;p&gt;Give a copy of the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.pot&lt;/span&gt;&lt;/tt&gt; file to the translator, changing the extension to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.po&lt;/span&gt;&lt;/tt&gt;. The&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.po&lt;/span&gt;&lt;/tt&gt; file is an editable source file used as input for the compilation step. The&lt;br /&gt;translator should update the header text in the file and provide translations for all of&lt;br /&gt;the strings.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="first"&gt;&amp;#8220;Compile&amp;#8221; the message catalog from the translation.&lt;/p&gt;&lt;p&gt;When the translator gives you back the completed &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.po&lt;/span&gt;&lt;/tt&gt; file, compile the text file to&lt;br /&gt;the binary catalog format using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;msgfmt&lt;/span&gt;&lt;/tt&gt;. The binary format is used by the runtime&lt;br /&gt;catalog lookup code.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="first"&gt;Load and activate the appropriate message catalog at runtime.&lt;/p&gt;&lt;p&gt;The final step is to add a few lines to your application to configure and load the message&lt;br /&gt;catalog and install the translation function. There are a couple of ways to do that, with&lt;br /&gt;associated trade-offs, and each is covered below.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Let&amp;#8217;s go through those steps in a little more detail, starting with the modifications you need to make to your code.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="creating-message-catalogs-from-source-code"&gt;&lt;h2&gt;Creating Message Catalogs from Source Code&lt;/h2&gt;&lt;p&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;gettext&lt;/span&gt;&lt;/tt&gt; works by finding literal strings embedded in your program in a database of translations, and pulling out the appropriate translated string.  There are several variations of the functions for accessing the catalog, depending on whether you are working with Unicode strings or not.  The usual pattern is to bind the lookup function you want to use to the name &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_&lt;/span&gt;&lt;/tt&gt; so that your code is not cluttered with lots of calls to functions with longer names.&lt;/p&gt;&lt;p&gt;The message extraction program, xgettext, looks for messages embedded in calls to the catalog lookup functions.  It understands different source languages, and uses an appropriate parser for each.  If you use aliases for the lookup functions or need to add extra functions, you can give xgettext the names of additional symbols to consider when extracting messages.&lt;/p&gt;&lt;p&gt;Here&amp;#8217;s a simple script with a single message ready to be translated:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gettext&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Set up message catalog access&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gettext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;translation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;gettext_example&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;locale&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ugettext&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;This message is in the script.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In this case I am using the Unicode version of the lookup function, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ugettext()&lt;/span&gt;&lt;/tt&gt;.  The text &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;quot;This&lt;/span&gt; &lt;span class="pre"&gt;message&lt;/span&gt; &lt;span class="pre"&gt;is&lt;/span&gt; &lt;span class="pre"&gt;in&lt;/span&gt; &lt;span class="pre"&gt;the&lt;/span&gt; &lt;span class="pre"&gt;script.&amp;quot;&lt;/span&gt;&lt;/tt&gt; is the message to be substituted from the catalog.  I&amp;#8217;ve enabled fallback mode, so if we run the script without a message catalog, the in-lined message is printed:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python gettext_example.py&lt;br /&gt;This message is in the script.&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;The next step is to extract the message(s) and create the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.pot&lt;/span&gt;&lt;/tt&gt; file, using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;pygettext.py&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ xgettext -d gettext_example -o gettext_example.pot gettext_example.py&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;The output file produced looks like:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;# SOME DESCRIPTIVE TITLE.&lt;br /&gt;# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER&lt;br /&gt;# This file is distributed under the same license as the PACKAGE package.&lt;br /&gt;# FIRST AUTHOR &amp;lt;EMAIL@ADDRESS&amp;gt;, YEAR.&lt;br /&gt;#&lt;br /&gt;#, fuzzy&lt;br /&gt;msgid ""&lt;br /&gt;msgstr ""&lt;br /&gt;"Project-Id-Version: PACKAGE VERSION\n"&lt;br /&gt;"Report-Msgid-Bugs-To: \n"&lt;br /&gt;"POT-Creation-Date: 2009-06-14 11:39-0400\n"&lt;br /&gt;"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"&lt;br /&gt;"Last-Translator: FULL NAME &amp;lt;EMAIL@ADDRESS&amp;gt;\n"&lt;br /&gt;"Language-Team: LANGUAGE &amp;lt;LL@li.org&amp;gt;\n"&lt;br /&gt;"MIME-Version: 1.0\n"&lt;br /&gt;"Content-Type: text/plain; charset=CHARSET\n"&lt;br /&gt;"Content-Transfer-Encoding: 8bit\n"&lt;br /&gt;&lt;br /&gt;#: gettext_example.py:16&lt;br /&gt;msgid "This message is in the script."&lt;br /&gt;msgstr ""&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Message catalogs are installed into directories organized by &lt;em&gt;domain&lt;/em&gt; and &lt;em&gt;language&lt;/em&gt;.  The domain is usually a unique value like your application name.  In this case, I used &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;gettext_example&lt;/span&gt;&lt;/tt&gt;.  The language value is provided by the user&amp;#8217;s environment at runtime, through one of the environment variables &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;LANGUAGE&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;LC_ALL&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;LC_MESSAGES&lt;/span&gt;&lt;/tt&gt;, or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;LANG&lt;/span&gt;&lt;/tt&gt;, depending on their configuration and platform.  My language is set to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;en_US&lt;/span&gt;&lt;/tt&gt; so that&amp;#8217;s what I&amp;#8217;ll be using in all of the examples below.&lt;/p&gt;&lt;p&gt;Now that we have the template, the next step is to create the required directory structure and copy the template in to the right spot.  I&amp;#8217;m going to use the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;locale&lt;/span&gt;&lt;/tt&gt; directory inside the PyMOTW source tree as the root of my message catalog directory, but you would typically want to use a directory accessible system-wide.  The full path to the catalog input source is &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;$localedir/$language/LC_MESSAGES/$domain.po&lt;/span&gt;&lt;/tt&gt;, and the actual catalog has the filename extension &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.mo&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;For my configuration, I need to copy &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;gettext_example.pot&lt;/span&gt;&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;locale/en_US/LC_MESSAGES/gettext_example.po&lt;/span&gt;&lt;/tt&gt; and edit it to change the values in the header and add my alternate messages.  The result looks like:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;# Messages from gettext_example.py.&lt;br /&gt;# Copyright (C) 2009 Doug Hellmann&lt;br /&gt;# Doug Hellmann &amp;lt;doug.hellmann@gmail.com&amp;gt;, 2009.&lt;br /&gt;#&lt;br /&gt;msgid ""&lt;br /&gt;msgstr ""&lt;br /&gt;"Project-Id-Version: PyMOTW 1.92\n"&lt;br /&gt;"Report-Msgid-Bugs-To: Doug Hellmann &amp;lt;doug.hellmann@gmail.com&amp;gt;\n"&lt;br /&gt;"POT-Creation-Date: 2009-06-07 10:31+EDT\n"&lt;br /&gt;"PO-Revision-Date: 2009-06-07 10:31+EDT\n"&lt;br /&gt;"Last-Translator: Doug Hellmann &amp;lt;doug.hellmann@gmail.com&amp;gt;\n"&lt;br /&gt;"Language-Team: US English &amp;lt;doug.hellmann@gmail.com&amp;gt;\n"&lt;br /&gt;"MIME-Version: 1.0\n"&lt;br /&gt;"Content-Type: text/plain; charset=UTF-8\n"&lt;br /&gt;"Content-Transfer-Encoding: 8bit\n"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#: gettext_example.py:16&lt;br /&gt;msgid "This message is in the script."&lt;br /&gt;msgstr "This message is in the en_US catalog."&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;The catalog is built from the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.po&lt;/span&gt;&lt;/tt&gt; file using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;msgformat&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ cd locale/en_US/LC_MESSAGES/; msgfmt -o gettext_example.mo gettext_example.po&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;And now when we run the script, the message from the catalog is printed instead of the in-line string:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python gettext_example.py&lt;br /&gt;This message is in the en_US catalog.&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="finding-message-catalogs-at-runtime"&gt;&lt;h2&gt;Finding Message Catalogs at Runtime&lt;/h2&gt;&lt;p&gt;As described above, the &lt;em&gt;locale directory&lt;/em&gt; containing the message catalogs is organized based on the language with catalogs named for the &lt;em&gt;domain&lt;/em&gt; of the program.  Different operating systems define their own default value, but &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;gettext&lt;/span&gt;&lt;/tt&gt; does not know all of these defaults.  The default locale directory is &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;sys.prefix&lt;/span&gt; &lt;span class="pre"&gt;+&lt;/span&gt; &lt;span class="pre"&gt;'/share/locale'&lt;/span&gt;&lt;/tt&gt;, but most of the time it is safer for you to always explicitly give a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;localedir&lt;/span&gt;&lt;/tt&gt; value than to depend on any default behavior.&lt;/p&gt;&lt;p&gt;The language portion of the path is taken from one of several environment variables that can be used to configure localization features (LANGUAGE, LC_ALL, LC_MESSAGES, and LANG).  The first variable found to be set is used.  Multiple languages can be selected by separating the values with a colon (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;:&lt;/span&gt;&lt;/tt&gt;).  We can illustrate how that works by creating a second message catalog and running a few experiments.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ cd locale/en_CA/LC_MESSAGES/; msgfmt -o gettext_example.mo gettext_example.po&lt;br /&gt;$ python gettext_find.py&lt;br /&gt;Catalogs: ['locale/en_US/LC_MESSAGES/gettext_example.mo']&lt;br /&gt;$ LANGUAGE=en_CA python gettext_find.py&lt;br /&gt;Catalogs: ['locale/en_CA/LC_MESSAGES/gettext_example.mo']&lt;br /&gt;$ LANGUAGE=en_CA:en_US python gettext_find.py&lt;br /&gt;Catalogs: ['locale/en_CA/LC_MESSAGES/gettext_example.mo', 'locale/en_US/LC_MESSAGES/gettext_example.mo']&lt;br /&gt;$ LANGUAGE=en_US:en_CA python gettext_find.py&lt;br /&gt;Catalogs: ['locale/en_US/LC_MESSAGES/gettext_example.mo', 'locale/en_CA/LC_MESSAGES/gettext_example.mo']&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Although &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;find()&lt;/span&gt;&lt;/tt&gt; shows the complete list of catalogs, only the first one in the sequence is actually loaded for message lookups.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python gettext_example.py&lt;br /&gt;This message is in the en_US catalog.&lt;br /&gt;$ LANGUAGE=en_CA python gettext_example.py&lt;br /&gt;This message is in the en_CA catalog.&lt;br /&gt;$ LANGUAGE=en_CA:en_US python gettext_example.py&lt;br /&gt;This message is in the en_CA catalog.&lt;br /&gt;$ LANGUAGE=en_US:en_CA python gettext_example.py&lt;br /&gt;This message is in the en_US catalog.&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="plural-values"&gt;&lt;h2&gt;Plural Values&lt;/h2&gt;&lt;p&gt;While simple message substitution will handle most of your translation needs, one of the special cases handled explicitly by &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;gettext&lt;/span&gt;&lt;/tt&gt; is pluralization.  Depending on the language, the difference between the singular and plural forms of a message may vary only by the ending of a single word, or the entire sentence structure may be different.  There may also be &lt;a class="reference external" href="http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms"&gt;different forms depending on the level of plurality&lt;/a&gt;.  To make managing plurals easier (and possible), there is a separate set of functions for asking for the plural form of a message.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;gettext&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;translation&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;translation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;gettext_plural&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;locale&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ungettext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%(num)d&lt;/span&gt;&lt;span class="s"&gt; means singular.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%(num)d&lt;/span&gt;&lt;span class="s"&gt; means plural.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Still need to add the values to the message ourself.&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;num&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ xgettext -L Python -d gettext_plural -o gettext_plural.pot gettext_plural.py&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Since there are alternate forms to be translated, the replacements are listed in an array.  Using an array allows translations for languages with multiple plural forms (Polish, &lt;a class="reference external" href="http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms"&gt;for example&lt;/a&gt;, has different forms indicating the relative quantity).&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;# SOME DESCRIPTIVE TITLE.&lt;br /&gt;# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER&lt;br /&gt;# This file is distributed under the same license as the PACKAGE package.&lt;br /&gt;# FIRST AUTHOR &amp;lt;EMAIL@ADDRESS&amp;gt;, YEAR.&lt;br /&gt;#&lt;br /&gt;#, fuzzy&lt;br /&gt;msgid ""&lt;br /&gt;msgstr ""&lt;br /&gt;"Project-Id-Version: PACKAGE VERSION\n"&lt;br /&gt;"Report-Msgid-Bugs-To: \n"&lt;br /&gt;"POT-Creation-Date: 2009-06-14 11:39-0400\n"&lt;br /&gt;"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"&lt;br /&gt;"Last-Translator: FULL NAME &amp;lt;EMAIL@ADDRESS&amp;gt;\n"&lt;br /&gt;"Language-Team: LANGUAGE &amp;lt;LL@li.org&amp;gt;\n"&lt;br /&gt;"MIME-Version: 1.0\n"&lt;br /&gt;"Content-Type: text/plain; charset=CHARSET\n"&lt;br /&gt;"Content-Transfer-Encoding: 8bit\n"&lt;br /&gt;"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"&lt;br /&gt;&lt;br /&gt;#: gettext_plural.py:15&lt;br /&gt;#, python-format&lt;br /&gt;msgid "%(num)d means singular."&lt;br /&gt;msgid_plural "%(num)d means plural."&lt;br /&gt;msgstr[0] ""&lt;br /&gt;msgstr[1] ""&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;In addition to filling in the translation strings, you will also need to describe the way plurals are formed so the library knows how to index into the array for any given count value.  The line &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;quot;Plural-Forms:&lt;/span&gt; &lt;span class="pre"&gt;nplurals=INTEGER;&lt;/span&gt; &lt;span class="pre"&gt;plural=EXPRESSION;\n&amp;quot;&lt;/span&gt;&lt;/tt&gt; includes two values to replace manually.  &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;nplurals&lt;/span&gt;&lt;/tt&gt; is an integer indicating the size of the array (the number of translations used) and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;plural&lt;/span&gt;&lt;/tt&gt; is a C language expression for converting the incoming quantity to an index in the array when looking up the translation.  The literal string &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;n&lt;/span&gt;&lt;/tt&gt; is replaced with the quantity passed to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ungettext()&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;For example, English includes two plural forms.  A quantity of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;0&lt;/span&gt;&lt;/tt&gt; is treated as plural (&amp;#8220;0 bananas&amp;#8221;).  The Plural-Forms entry should look like:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;Plural-Forms: nplurals=2; plural=n != 1;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;The singular translation would then go in position 0, and the plural translation in position 1.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;# Messages from gettext_plural.py&lt;br /&gt;# Copyright (C) 2009 Doug Hellmann&lt;br /&gt;# This file is distributed under the same license as the PyMOTW package.&lt;br /&gt;# Doug Hellmann &amp;lt;doug.hellmann@gmail.com&amp;gt;, 2009.&lt;br /&gt;#&lt;br /&gt;#, fuzzy&lt;br /&gt;msgid ""&lt;br /&gt;msgstr ""&lt;br /&gt;"Project-Id-Version: PyMOTW 1.92\n"&lt;br /&gt;"Report-Msgid-Bugs-To: Doug Hellmann &amp;lt;doug.hellmann@gmail.com&amp;gt;\n"&lt;br /&gt;"POT-Creation-Date: 2009-06-14 09:29-0400\n"&lt;br /&gt;"PO-Revision-Date: 2009-06-14 09:29-0400\n"&lt;br /&gt;"Last-Translator: Doug Hellmann &amp;lt;doug.hellmann@gmail.com&amp;gt;\n"&lt;br /&gt;"Language-Team: en_US &amp;lt;doug.hellmann@gmail.com&amp;gt;\n"&lt;br /&gt;"MIME-Version: 1.0\n"&lt;br /&gt;"Content-Type: text/plain; charset=UTF-8\n"&lt;br /&gt;"Content-Transfer-Encoding: 8bit\n"&lt;br /&gt;"Plural-Forms: nplurals=2; plural=n != 1;"&lt;br /&gt;&lt;br /&gt;#: gettext_plural.py:15&lt;br /&gt;#, python-format&lt;br /&gt;msgid "%(num)d means singular."&lt;br /&gt;msgid_plural "%(num)d means plural."&lt;br /&gt;msgstr[0] "In en_US, %(num)d is singular."&lt;br /&gt;msgstr[1] "In en_US, %(num)d is plural."&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;If we run the test script a few times after the catalog is compiled, you can see how different values of N are converted to indexes for the translation strings.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ cd locale/en_US/LC_MESSAGES/; msgfmt -o gettext_plural.mo gettext_plural.po&lt;br /&gt;$ python gettext_plural.py 0&lt;br /&gt;In en_US, 0 is plural.&lt;br /&gt;$ python gettext_plural.py 1&lt;br /&gt;In en_US, 1 is singular.&lt;br /&gt;$ python gettext_plural.py 2&lt;br /&gt;In en_US, 2 is plural.&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="application-vs-module-localization"&gt;&lt;h2&gt;Application vs. Module Localization&lt;/h2&gt;&lt;p&gt;The scope of your translation effort defines how you install and use the &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;gettext&lt;/span&gt;&lt;/tt&gt; functions in your code.&lt;/p&gt;&lt;div class="section" id="application-localization"&gt;&lt;h3&gt;Application Localization&lt;/h3&gt;&lt;p&gt;For application-wide translations, it would be acceptable to install a function like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ungettext()&lt;/span&gt;&lt;/tt&gt; globally using the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;__builtins__&lt;/span&gt;&lt;/tt&gt; namespace because you have control over the top-level of the application&amp;#8217;s code.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gettext&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;gettext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;gettext_example&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;locale&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;unicode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;ngettext&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;This message is in the script.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;install()&lt;/span&gt;&lt;/tt&gt; function binds &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;gettext()&lt;/span&gt;&lt;/tt&gt; to the name &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;_()&lt;/span&gt;&lt;/tt&gt; in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;__builtins__&lt;/span&gt;&lt;/tt&gt; namespace.  It also adds &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ngettext()&lt;/span&gt;&lt;/tt&gt; and other functions listed in &lt;em&gt;names&lt;/em&gt;.  If &lt;em&gt;unicode&lt;/em&gt; is true, the Unicode versions of the functions are used instead of the default ASCII versions.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="module-localization"&gt;&lt;h3&gt;Module Localization&lt;/h3&gt;&lt;p&gt;For a library, or individual module, modifying &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;__builtins__&lt;/span&gt;&lt;/tt&gt; is not a good idea because you don&amp;#8217;t know what conflicts you might introduce with an application global value.  You can import or re-bind the names of translation functions by hand at the top of your module.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gettext&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gettext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;translation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;gettext_example&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;locale&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ugettext&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;ngettext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ungettext&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;This message is in the script.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/gettext.html"&gt;gettext&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for this module.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://www.gnu.org/software/gettext/"&gt;GNU gettext&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The message catalog formats, API, etc. for this module are all based on the original gettext package from GNU.  The catalog file formats are compatible, and the command line scripts have similar options (if not identical).  The &lt;a class="reference external" href="http://www.gnu.org/software/gettext/manual/gettext.html"&gt;GNU gettext manual&lt;/a&gt; has a detailed description of the file formats and describes GNU versions of the tools for working with them.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://www.python.org/workshops/1997-10/proceedings/loewis.html"&gt;Internationalizing Python&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;A paper by Martin von Löwis about techniques for internationalization of Python applications.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.djangoproject.com/en/dev/topics/i18n/"&gt;Django Internationalization&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;Another good source of information on using gettext, including real-life examples.&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The &lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/gettext/"&gt;canonical version&lt;/a&gt; of this article&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-401767123904814065?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/401767123904814065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=401767123904814065' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/401767123904814065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/401767123904814065'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/06/pymotw-gettext.html' title='PyMOTW: gettext'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-3499824609684973039</id><published>2009-06-14T08:39:00.001-04:00</published><updated>2009-06-14T08:39:14.503-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OS X'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>installing GNU gettext for use with Python on OS X</title><content type='html'>I've been working on my blog post about Python's gettext module for the past couple of mornings, and ran into a snag.  The documentation claims that the Python source distribution includes all the tools you'll need, but when I got to the point where I wanted to write examples of internationalizing plural strings, pygettext.py wasn't working.&lt;br /&gt;&lt;br /&gt;It worked great for extracting individual string messages up to that point, but refused to extract messages wrapped in the ungettext() call, even when I used what seemed to be the appropriate command line options. I ended up installing the GNU gettext tools and using xgettext instead.  Installation took me longer than I expected, so I'm documenting the process I went through here.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Fink or MacPorts: Not so much.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since OS X doesn't ship with a version of gettext by default, and there doesn't seem to be one in the Xcode package (Apple has their own internationalization tools), I needed to find a copy elsewhere.  &lt;br /&gt;&lt;br /&gt;Ages ago I had installed &lt;a href="http://www.finkproject.org/"&gt;fink&lt;/a&gt; as an "easy" way to grab copies of these sorts of utilities.  However, it seems that somewhere along the line the version of fink I have stopped working (probably due to upgrading to 10.5, I haven't tried using fink or FinkCommander directly in some time).  After wiping and reinstalling, I was pleased to find a slightly old version (0.14.5) of gettext installed as part of the default set of packages.  Unfortunately, xgettext wasn't included in the package at all.&lt;br /&gt;&lt;br /&gt;Next, I grabbed a copy of &lt;a href="http://www.macports.org/"&gt;MacPorts&lt;/a&gt;, a competitor to fink.  Although I've been warned off of MacPorts by a few people I trust, others have had no problems with it.  Installation was fairly easy, and as with fink it installed everything to its own directory tree (under &lt;code&gt;/opt/local&lt;/code&gt;).  Once I had the port program installed, the next step was to run:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;$ sudo port install gettext&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It downloaded several dependencies, patched the source, compiled everything, and installed it.  Voila!  Well, not so much.  &lt;br /&gt;&lt;br /&gt;Even though the most current version of gettext (0.17) was installed, and the documentation clearly described the included Python language support, the binary refused to recognize any language other than C.  &lt;br /&gt;&lt;br /&gt;Scratch that.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Compiling from Source: Partial Success&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since MacPorts had to download the package and compile it anyway, I decided to go ahead and do that on my own.  I was a little wary because I wasn't exactly sure what port was doing in its "patching" step, but I thought I would give it a try anyway.  I snagged the most recent tarball from the &lt;a href="http://www.gnu.org/software/gettext/"&gt;gettext site&lt;/a&gt; and ran the usual&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;$ ./configure&lt;br /&gt;$ make&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;That gave me a binary for xgettext inside the source directory, and testing it against my Python source yielded the results I wanted.  A simple .pot file was extracted with the original message strings and placeholders for singular and plural translations.&lt;br /&gt;&lt;br /&gt;Next, I thought I'd get clever and install the results into the virtualenv I use for working on PyMOTW.  Re-configuring with my --prefix set to $VIRTUAL_ENV, rebuilding, then running &lt;code&gt;make install&lt;/code&gt; copied the binaries and a bunch of associated data files right where I expected them to be.  And the binary only recognized the C language.&lt;br /&gt;&lt;br /&gt;After a little more fighting, I did manage to get it working by installing with a prefix of $VIRTUAL_ENV/gettext and adding $VIRTUAL_ENV/gettext/bin to my PATH.  I'm not sure if the problem was solved by clearing out an older, bad version of xgettext from elsewhere in my path or if using $VIRTUAL_ENV as the prefix somehow confused the install script.&lt;br /&gt;&lt;br /&gt;Conclusion:  I think I understand why internationalization is frequently the last feature dealt with in a project.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-3499824609684973039?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/3499824609684973039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=3499824609684973039' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3499824609684973039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3499824609684973039'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/06/installing-gnu-gettext-for-use-with.html' title='installing GNU gettext for use with Python on OS X'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-4738919025867248130</id><published>2009-06-11T13:00:00.001-04:00</published><updated>2009-06-11T13:01:48.203-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='PyATL'/><title type='text'>Book Review: The Economics of Iterative Development</title><content type='html'>&lt;iframe src="http://rcm.amazon.com/e/cm?t=hellflynet-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0321509358&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;float:left;margin-right: 1em;margin-bottom:1em;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Economics of Iterative Software Development&lt;/strong&gt;, by Walker Royce, Kurt Bittner, and Mike Perrow, covers techniques for achieving more predictable results with development projects.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Disclaimer: I received a review copy of this book through the PyATL Book Club.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;The goal of the book is to encourage adoption of &lt;em&gt;iterative development processes&lt;/em&gt;, rather than the old-fashioned waterfall model (does anyone really still use that model?).  In the authors' view, iterative processes, where one builds a rough version of a product and continually refine it over time, yield better results in terms of predictable schedule and meeting real requirements.  This isn't a new idea, and they make reference to agile processes such as XP and Scrum, along with RUP.  But the book isn't necessarily a guide to a specific set of processes.  It's framed as more of an argument in favor of the entire class of techniques represented by modern development methodologies.&lt;br /&gt;&lt;br /&gt;The authors clearly have experience with development processes and evaluating and improving performance of teams.  Royce is a VP from IBM's Rational Services group and a contributor to RUP.  Bettner is a CTO at Ivar Jacobsen Consulting and also contributed to RUP as well as jazz.net. Perrow is a writer within the Rational group at IBM.  Their experience shows in the authoritative tone the book takes when presenting best practices.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"day-to-day decisions are dominated by value judgements, cost trade-offs, ..."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;They start from the premise that software development is less of an engineering practice and more like a creative endeavor such as producing a film.  Only 1/3 of movies deliver on time and within budget, for example. The comparison resonates with me since I have always viewed development work as more creative than mechanical manufacturing or engineering, although I was never quite sure other types of engineering were as non-creative as they are portrayed.&lt;br /&gt;&lt;br /&gt;The more I think about it though, the more I am inclined to see managing software development as managing invention, which is even farther from typical engineering than movie production. With software, no two products or projects are exactly the same, so the "best practices" we learn have to be adapted for every situation. &lt;br /&gt;&lt;br /&gt;They go on to describe a generalized history of approaches to software development processes.  In the '60's and '70's the attitude was "craftsmanship", with lots of customization of tools and processes. In the '80's and '90's the trend was towards an engineering approach, but it still had a lot of innovation with new technology and techniques. Recent techniques have paid more attention to risk, taking advantage of automation.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Write code. Less of it. Mostly high-level languages.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The authors a couple of primary ways to reduce risk in development.  The first is using  propose component-based and service-oriented architectures.  By isolating parts of the implementation from one another and connecting them through established interfaces, you can iterate over different parts improving as needed.  There is also an emphasis on reducing the amount of "human generated" source code, either through high-level languages, off-the-shelf components, or code generation (unsurprisingly, they specifically mention UML-based code generators).&lt;br /&gt;&lt;br /&gt;This was about the point in the book where I realized that it was missing the material needed to back up the assertions and claims being made.  With a name like "The Economics of Iterative Software Development," I expected to find more statistics and supporting research material than is provided. I don't disagree with any of the authors' conclusions (indeed, they're hardly new insights for anyone who has read a couple of books on agile methodologies).  The problem is if I was trying to use this book to convince someone who did not already accept the premise, I wouldn't have any basis for an argument.&lt;br /&gt;&lt;br /&gt;This lack of background was particularly evident in chapter 7, where they talk about ways to "accelerate cultural change" to iterative development by choosing a high-profile project instead of easing into it with a pilot project.  Their rationale is that the people assigned to work on high-profile projects are typically the better performers already, and if you get their buy-in, they will make the change work because of their dedication. The trick is getting the buy-in in the first place, of course.&lt;br /&gt;&lt;br /&gt;I found the book interesting, well written, and worth reading.  It doesn't quite stand on its own, though, if you're looking for ammunition to change your boss' mind about process.  If you have already decided to go with an iterative process, it will reinforce your decision and provide guidance to make it work (particularly in the appendix).  But it didn't live up to my expectations, based on the title.&lt;br /&gt;&lt;br /&gt;Updated: Check out my notes for this book on &lt;a href="http://readernaut.com/doughellmann/books/0321509358/the-economics-of-iterative-software-development/?page=1"&gt;readernaut.com&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-4738919025867248130?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/4738919025867248130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=4738919025867248130' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/4738919025867248130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/4738919025867248130'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/06/book-review-economics-of-iterative.html' title='Book Review: The Economics of Iterative Development'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-3358655730711180676</id><published>2009-06-11T07:45:00.001-04:00</published><updated>2009-06-11T07:45:46.085-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='PyATL'/><title type='text'>Using Readernaut for taking notes on books</title><content type='html'>Over the past couple of months I've been working on reviving the PyATL book club.  We received our first batch of books from Addison-Wesley/Pearson Education in time to distribute them at our meeting last month.  I'll be posting my review soon, but before I do that I wanted to share my experiences with Nathan Borror's excellent &lt;a href="http://readernaut.com/"&gt;http://readernaut.com/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The site is easy to use.  Once you have an account, just use the search field to find a book, either already in the Readernaut catalog or at Amazon.  Add it to your shelf, then record your progress and notes as you read.  In true web 2.0 fashion, you can connect with other readers and follow their progress (indeed, I may be coming late to the party on this one, because after I signed up I found &lt;a href="http://readernaut.com/doughellmann/contacts/"&gt;a bunch of other Pythonistas&lt;/a&gt; already using the site to post notes and reviews about the books they're reading).&lt;br /&gt;&lt;br /&gt;After a bit of experimentation, I'm hooked.  I used the site to take notes about &lt;a href="http://readernaut.com/doughellmann/books/0321509358/the-economics-of-iterative-software-development/"&gt;my first book club book&lt;/a&gt;, and am finding the results very helpful while preparing the summary for my review.  I can record notes, quotes, and remarks as separate types of comments.  All include page numbers, so as I build the review I don't even have to go hunting through the book for references.&lt;br /&gt;&lt;br /&gt;Besides posting my own material, I've found a &lt;a href="http://readernaut.com/malcolmt/notes/7008/"&gt;couple&lt;/a&gt; of &lt;a href="http://readernaut.com/ubernostrum/notes/6924/"&gt;interesting-looking&lt;/a&gt; &lt;a href="http://readernaut.com/wilsonminer/books/0805087249/an-army-at-dawn/"&gt;titles&lt;/a&gt; among the books others are reading.  As though I needed help finding more books to read.&lt;br /&gt;&lt;br /&gt;If you take your reading seriously, check out &lt;a href="http://readernaut.com/"&gt;http://readernaut.com/&lt;/a&gt; as a convenient way to keep up with your notes.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-3358655730711180676?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/3358655730711180676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=3358655730711180676' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3358655730711180676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3358655730711180676'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/06/using-readernaut-for-taking-notes-on.html' title='Using Readernaut for taking notes on books'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-570574384036804312</id><published>2009-06-05T08:50:00.001-04:00</published><updated>2009-06-05T08:50:59.472-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sphinxcontrib.paverutils'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='sphinx'/><title type='text'>new project: sphinxcontrib-paverutils</title><content type='html'>Kevin Dangoor's &lt;a href="http://www.blueskyonmars.com/projects/paver/"&gt;Paver&lt;/a&gt; includes basic integration for &lt;a href="http://sphinx.pocoo.org/"&gt;Sphinx&lt;/a&gt;, the excellent document production toolkit from Georg Brandl.  As I have &lt;a href="http://blog.doughellmann.com/2009/02/writing-technical-documentation-with.html"&gt;written before&lt;/a&gt;, however, the default integration didn't quite meet my needs for producing different forms of output from the same inputs.&lt;br /&gt;&lt;br /&gt;Georg has opened the &lt;a href="http://bitbucket.org/birkenfeld/sphinx-contrib/"&gt;sphinxcontrib repository&lt;/a&gt; on BitBucket for developers who want to collaborate on providing unofficial extensions to Sphinx, so I decided to go ahead and package up the alternate integration I use and release it in case someone else finds it helpful.  The result is &lt;a href="http://www.doughellmann.com/projects/sphinxcontrib.paverutils/"&gt;sphinxcontrib.paverutils&lt;/a&gt;.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-570574384036804312?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/570574384036804312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=570574384036804312' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/570574384036804312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/570574384036804312'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/06/new-project-sphinxcontrib-paverutils.html' title='new project: sphinxcontrib-paverutils'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-3233067100010337576</id><published>2009-06-03T07:10:00.001-04:00</published><updated>2009-06-05T07:27:43.409-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PyCon'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>python-authors mailing list</title><content type='html'>At PyCon this year, a group of authors and editors met to start building the &lt;a href="http://us.pycon.org/2009/openspace/WritingAboutPython/"&gt;writing sub-community&lt;/a&gt; for people interested in Python-related topics appearing online and in print.  One of the suggestions that came out of the meeting was to establish a new SIG mailing list, hosted on python.org.  I'm pleased to announce that the &lt;a href="http://mail.python.org/mailman/listinfo/python-authors"&gt;python-authors list&lt;/a&gt; has been established and is ready to host traffic!&lt;br /&gt;&lt;br /&gt;If you have any experience or interest in writing, editing, or reviewing technical writing such as blog posts, magazine articles, or books, this list is for you.  We'll be trading tips, looking for collaborators for new projects, and just generally talking shop.&lt;br /&gt;&lt;br /&gt;I hope you'll &lt;a href="http://mail.python.org/mailman/listinfo/python-authors"&gt;join us&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;Updated 5 June 2009: Unfortunately I've had to set the list subscription to moderated to avoid spammers.  The list itself is still unmoderated, and I will try to approve requests for new subscriptions as quickly as possible.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-3233067100010337576?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/3233067100010337576/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=3233067100010337576' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3233067100010337576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3233067100010337576'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/06/python-authors-mailing-list.html' title='python-authors mailing list'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-6040156047112580549</id><published>2009-05-31T18:46:00.001-04:00</published><updated>2009-05-31T18:46:48.811-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>Data persistence tools in the Python Standard Library</title><content type='html'>&lt;em&gt;This is the first in a new sub-series of Python Module of the Week posts with a feature-based introduction to modules in the standard library, organized by what your goal might be.  Each article may include cross-references to several modules from different parts of the library, and show how they relate to one another.  Feedback is welcome, as usual.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id="content"&gt;&lt;div class="section" id="data-persistence-and-exchange"&gt;&lt;br /&gt;&lt;span id="article-data-persistence"&gt;&lt;/span&gt;&lt;h1&gt;Data Persistence and Exchange&lt;a class="headerlink" href="#data-persistence-and-exchange" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;Python provides several modules for storing data.  There are basically two aspects to persistence: converting the in-memory object back and forth into a format for saving it, and working with the storage of the converted data.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="section" id="serializing-objects"&gt;&lt;br /&gt;&lt;h2&gt;Serializing Objects&lt;a class="headerlink" href="#serializing-objects" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Python includes two modules capable of converting objects into a transmittable or storable format (&lt;em&gt;serializing&lt;/em&gt;): &lt;a title="Python object serialization" class="reference external" href="http://www.doughellmann.com/PyMOTW/pickle/index.html#module-pickle"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;pickle&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt; and &lt;a title="JavaScript Object Notation Serializer" class="reference external" href="http://www.doughellmann.com/PyMOTW/json/index.html#module-json"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;.  It is most common to use &lt;a title="Python object serialization" class="reference external" href="http://www.doughellmann.com/PyMOTW/pickle/index.html#module-pickle"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;pickle&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;, since there is a fast C implementation and it is integrated with some of the other standard library modules that actually store the serialized data, such as &lt;a title="Persistent storage of arbitrary Python objects" class="reference external" href="http://www.doughellmann.com/PyMOTW/shelve/index.html#module-shelve"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;shelve&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;.  Web-based applications may want to examine &lt;a title="JavaScript Object Notation Serializer" class="reference external" href="http://www.doughellmann.com/PyMOTW/json/index.html#module-json"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;, however, since it integrates better with some of the existing web service storage applications.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="section" id="storing-serialized-objects"&gt;&lt;br /&gt;&lt;h2&gt;Storing Serialized Objects&lt;a class="headerlink" href="#storing-serialized-objects" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Once the in-memory object is converted to a storable format, the next step is to decide how to store the data.  A simple flat-file with serialized objects written one after the other works for data that does not need to be indexed in any way.  But Python includes a collection of modules for storing key-value pairs in a simple database using one of the DBM format variants.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The simplest interface to take advantage of the DBM format is provided by &lt;a title="Persistent storage of arbitrary Python objects" class="reference external" href="http://www.doughellmann.com/PyMOTW/shelve/index.html#module-shelve"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;shelve&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;.  Simply open the shelve file, and access it through a dictionary-like API.  Objects saved to the shelve are automatically pickled and saved without any extra work on your part.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;One drawback of shelve is that with the default interface you can&amp;#8217;t guarantee which DBM format will be used.  That won&amp;#8217;t matter if your application doesn&amp;#8217;t need to share the database files between hosts with different libraries, but if that is needed you can use one of the classes in the module to ensure a specific format is selected (&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/shelve/index.html#shelve-shelf-types"&gt;&lt;em&gt;Specific Shelf Types&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;If you&amp;#8217;re going to be passing a lot of data around via JSON anyway, using &lt;a title="JavaScript Object Notation Serializer" class="reference external" href="http://www.doughellmann.com/PyMOTW/json/index.html#module-json"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt; and &lt;a title="anydbm provides a generic dictionary-like interface to DBM-style, string-keyed databases" class="reference external" href="http://www.doughellmann.com/PyMOTW/anydbm/index.html#module-anydbm"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;anydbm&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt; can provide another persistence mechanism.  Since the DBM database keys and values must be strings, however, the objects won&amp;#8217;t be automatically re-created when you access the value in the database.&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="section" id="relational-databases"&gt;&lt;br /&gt;&lt;h2&gt;Relational Databases&lt;a class="headerlink" href="#relational-databases" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;The excellent &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;sqlite3&lt;/span&gt;&lt;/tt&gt; in-process relational database is available with most Python distributions.  It stores its database in memory or in a local file, and all access is from within the same process, so there is no network lag.  The compact nature of &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;sqlite3&lt;/span&gt;&lt;/tt&gt; makes it especially well suited for embedding in desktop applications or development versions of web apps.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;All access to the database is through the Python DBI 2.0 API, by default, as no object relational mapper (ORM) is included.  The most popular general purpose ORM is &lt;a class="reference external" href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;, but others such as Django&amp;#8217;s native ORM layer also support SQLite.  SQLAlchemy is easy to install and set up, but if your objects aren&amp;#8217;t very complicated and you are worried about overhead, you may want to use the DBI interface directly.&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="section" id="data-exchange-through-standard-formats"&gt;&lt;br /&gt;&lt;h2&gt;Data Exchange Through Standard Formats&lt;a class="headerlink" href="#data-exchange-through-standard-formats" title="Permalink to this headline"&gt;¶&lt;/a&gt;&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Although not usually considered a true persistence format &lt;a title="Read and write comma separated value files." class="reference external" href="http://www.doughellmann.com/PyMOTW/csv/index.html#module-csv"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;csv&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;, or comma-separated-value, files can be an effective way to migrate data between applications.  Most spreadsheet programs and databases support both export and import using CSV, so dumping data to a CSV file is frequently the simplest way to move data out of your application and into an analysis tool.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-6040156047112580549?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/6040156047112580549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=6040156047112580549' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6040156047112580549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6040156047112580549'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/05/data-persistence-tools-in-python.html' title='Data persistence tools in the Python Standard Library'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-3876580778418251412</id><published>2009-05-25T11:38:00.001-04:00</published><updated>2009-05-25T11:38:59.899-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>Japanese translation of PyMOTW</title><content type='html'>I am very pleased to announce that &lt;a href="http://d.hatena.ne.jp/t2y-1979/"&gt;Tetsuya Morimoto&lt;/a&gt; is creating a &lt;a href="http://d.hatena.ne.jp/t2y-1979/20090525/1243227350"&gt;Japanese translation&lt;/a&gt; of the Python Module of the Week series. &lt;br /&gt;&lt;br /&gt;Tetsuya has used Python for 1.5 years. He has experience at a Linux Distributor using Python with yum, anaconda, and rpm-tools while building RPM packages. Now, he uses it to make useful tools for himself, and is interested in application frameworks such as Django, mercurial and wxPython. Tetsuya is a member of &lt;a href="http://www.python.jp/Zope/"&gt;Python Japan User's Group&lt;/a&gt; and &lt;a href="http://groups.google.co.jp/group/python-code-reading"&gt;Python Code Reading&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Thanks, Tetsuya!&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-3876580778418251412?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/3876580778418251412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=3876580778418251412' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3876580778418251412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3876580778418251412'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/05/japanese-translation-of-pymotw.html' title='Japanese translation of PyMOTW'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-5986814553367627571</id><published>2009-05-24T13:57:00.001-04:00</published><updated>2009-05-24T13:57:10.799-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>PyMOTW: json</title><content type='html'>&lt;div class="section" id="module-json"&gt;&lt;br /&gt;&lt;h1&gt;json &amp;#8211; JavaScript Object Notation Serializer&lt;/h1&gt;&lt;table class="docutils field-list" frame="void" rules="none"&gt;&lt;col class="field-name"&gt;&lt;/col&gt;&lt;col class="field-body"&gt;&lt;/col&gt;&lt;tbody valign="top"&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Purpose:&lt;/th&gt;&lt;td class="field-body"&gt;Encode Python objects as JSON strings, and decode JSON strings into Python objects.&lt;/td&gt;&lt;/tr&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Python Version:&lt;/th&gt;&lt;td class="field-body"&gt;2.6&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;The &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/tt&gt; module provides an API similar to &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;pickle&lt;/span&gt;&lt;/tt&gt; for converting in-memory Python objects to a serialized representation known as &amp;#8220;JavaScript Object Notation&amp;#8221;.  Unlike pickle, JSON has the benefit of having implementations in many languages (especially JavaScript), making it suitable for inter-application communication.  JSON is probably most widely used for communicating between the web server and client in an AJAX application, but is not limited to that problem domain.&lt;/p&gt;&lt;div class="section" id="encoding-and-decoding-simple-data-types"&gt;&lt;h2&gt;Encoding and Decoding Simple Data Types&lt;/h2&gt;&lt;p&gt;The encoder understands Python&amp;#8217;s native types by default (int, float, list, tuple, dict).&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;DATA:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;data_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;JSON:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_string&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Values are encoded in a manner very similar to Python&amp;#8217;s &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;repr()&lt;/span&gt;&lt;/tt&gt; output.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_simple_types.py&lt;br /&gt;DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]&lt;br /&gt;JSON: [{"a": "A", "c": 3.0, "b": [2, 4]}]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Encoding, then re-decoding may not give exactly the same type of object.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;data_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ENCODED:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_string&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;DECODED:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decoded&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ORIGINAL:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;DECODED :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;For example, tuples are converted to JSON lists.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_simple_types_decode.py&lt;br /&gt;ENCODED: [{"a": "A", "c": 3.0, "b": [2, 4]}]&lt;br /&gt;DECODED: [{u'a': u'A', u'c': 3.0, u'b': [2, 4]}]&lt;br /&gt;ORIGINAL: &amp;lt;type 'tuple'&amp;gt;&lt;br /&gt;DECODED : &amp;lt;type 'list'&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="human-consumable-vs-compact-output"&gt;&lt;h2&gt;Human-consumable vs. Compact Output&lt;/h2&gt;&lt;p&gt;Another benefit of JSON over pickle is that the results are human-readable.  The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;dumps()&lt;/span&gt;&lt;/tt&gt; function accepts several arguments to make the output even nicer.  For example, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;sort_keys&lt;/span&gt;&lt;/tt&gt; tells the encoder to output the keys of a dictionary in sorted, instead of random, order.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;DATA:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;unsorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;JSON:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;SORT:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;UNSORTED MATCH:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unsorted&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;SORTED MATCH  :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Sorting makes it easier to scan the results by eye, and also makes it possible to compare JSON output in tests.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_sort_keys.py&lt;br /&gt;DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]&lt;br /&gt;JSON: [{"a": "A", "c": 3.0, "b": [2, 4]}]&lt;br /&gt;SORT: [{"a": "A", "b": [2, 4], "c": 3.0}]&lt;br /&gt;UNSORTED MATCH: False&lt;br /&gt;SORTED MATCH  : True&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;For highly-nested data structures, you will want to specify a value for &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;indent&lt;/span&gt;&lt;/tt&gt;, so the output is formatted nicely as well.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;DATA:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;NORMAL:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;INDENT:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;When indent is a non-negative integer, the output more closely resembles that of &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;pprint&lt;/span&gt;&lt;/tt&gt;, with leading spaces for each level of the data structure matching the indent level.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_indent.py&lt;br /&gt;DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]&lt;br /&gt;NORMAL: [{"a": "A", "b": [2, 4], "c": 3.0}]&lt;br /&gt;INDENT: [&lt;br /&gt;  {&lt;br /&gt;    "a": "A",&lt;br /&gt;    "b": [&lt;br /&gt;      2,&lt;br /&gt;      4&lt;br /&gt;    ],&lt;br /&gt;    "c": 3.0&lt;br /&gt;  }&lt;br /&gt;]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Verbose output like this increases the number of bytes needed to transmit the same amount of data, however, so it isn&amp;#8217;t the sort of thing you necessarily want to use in a production environment.  In fact, you may want to adjust the settings for separating data in the encoded output to make it even more compact than the default.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;DATA:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;repr(data)             :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;dumps(data)            :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;dumps(data, indent=2)  :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;dumps(data, separators):&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;separators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;separators&lt;/span&gt;&lt;/tt&gt; argument to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;dumps()&lt;/span&gt;&lt;/tt&gt; should be a tuple containing the strings to separate items in a list and keys from values in a dictionary.  The default is &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;(',&lt;/span&gt; &lt;span class="pre"&gt;',&lt;/span&gt; &lt;span class="pre"&gt;':&lt;/span&gt; &lt;span class="pre"&gt;')&lt;/span&gt;&lt;/tt&gt;. By removing the whitespace, we can produce a more compact output.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_compact_encoding.py&lt;br /&gt;DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]&lt;br /&gt;repr(data)             : 35&lt;br /&gt;dumps(data)            : 35&lt;br /&gt;dumps(data, indent=2)  : 76&lt;br /&gt;dumps(data, separators): 29&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="encoding-dictionaries"&gt;&lt;h2&gt;Encoding Dictionaries&lt;/h2&gt;&lt;p&gt;The JSON format expects the keys to a dictionary to be strings.  If you have other types as keys in your dictionary, trying to encode the object will produce a TypeError.  One way to work around that limitation is to skip over non-string keys using the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;skipkeys&lt;/span&gt;&lt;/tt&gt; argument:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;d&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,):&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;D tuple&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;First attempt&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Second attempt&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skipkeys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Rather than raising an exception, the non-string key is simply ignored.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_skipkeys.py&lt;br /&gt;First attempt&lt;br /&gt;ERROR: key ('d',) is not a string&lt;br /&gt;&lt;br /&gt;Second attempt&lt;br /&gt;[{"a": "A", "c": 3.0, "b": [2, 4]}]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="working-with-your-own-types"&gt;&lt;h2&gt;Working with Your Own Types&lt;/h2&gt;&lt;p&gt;All of the examples so far have used Pythons built-in types because those are supported by &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/tt&gt; natively.  It isn&amp;#8217;t uncommon, of course, to have your own types that you want to be able to encode as well.  There are two ways to do that.&lt;/p&gt;&lt;p&gt;First, we&amp;#8217;ll need a class to encode:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__repr__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;lt;MyObj(&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;)&amp;gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The simple way of encoding a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MyObj&lt;/span&gt;&lt;/tt&gt; instance is to define a function to convert an unknown type to a known type.  You don&amp;#8217;t have to do the encoding yourself, just convert one object to another.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json_myobj&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json_myobj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MyObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;instance value goes here&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;First attempt&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;convert_to_builtin_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;default(&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="c"&gt;# Convert objects to a dictionary of their representation&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__class__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__class__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;br /&gt;          &lt;span class="s"&gt;&amp;#39;__module__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__module__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;          &lt;span class="p"&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;With default&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;convert_to_builtin_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;convert_to_builtin_type()&lt;/span&gt;&lt;/tt&gt;, instances of classes not recognized by &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/tt&gt; are converted to dictionaries with enough information to re-create the object if a program has access to the Python modules necessary.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_dump_default.py&lt;br /&gt;First attempt&lt;br /&gt;ERROR: &amp;lt;MyObj(instance value goes here)&amp;gt; is not JSON serializable&lt;br /&gt;&lt;br /&gt;With default&lt;br /&gt;default( &amp;lt;MyObj(instance value goes here)&amp;gt; )&lt;br /&gt;{"s": "instance value goes here", "__module__": "json_myobj", "__class__": "MyObj"}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;To decode the results and create a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MyObj&lt;/span&gt;&lt;/tt&gt; instance, we need to tie in to the decoder so we can import the class from the module and create the instance.  For that, we use the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;object_hook&lt;/span&gt;&lt;/tt&gt; argument to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;loads()&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;The object_hook is called for each dictionary decoded from the incoming data stream, giving us a chance to convert the dictionary to another type of object.  The hook function should return the object it wants the calling application to receive instead of the dictionary.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dict_to_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__class__&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;class_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;__class__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;module_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;__module__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;__import__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;MODULE:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;class_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;CLASS:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;ascii&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;INSTANCE ARGS:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;inst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;inst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;inst&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;encoded_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;[{&amp;quot;s&amp;quot;: &amp;quot;instance value goes here&amp;quot;, &amp;quot;__module__&amp;quot;: &amp;quot;json_myobj&amp;quot;, &amp;quot;__class__&amp;quot;: &amp;quot;MyObj&amp;quot;}]&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;myobj_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoded_object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;object_hook&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dict_to_object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;myobj_instance&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Since &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/tt&gt; converts string values to unicode objects, we need to re-encode them as ASCII strings before using them as keyword arguments to the class constructor.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_load_object_hook.py&lt;br /&gt;MODULE: &amp;lt;module 'json_myobj' from '/Users/dhellmann/Documents/PyMOTW/src/PyMOTW/json/json_myobj.pyc'&amp;gt;&lt;br /&gt;CLASS: &amp;lt;class 'json_myobj.MyObj'&amp;gt;&lt;br /&gt;INSTANCE ARGS: {'s': u'instance value goes here'}&lt;br /&gt;[&amp;lt;MyObj(instance value goes here)&amp;gt;]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Similar hooks are available for the built-in types integers (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;parse_int&lt;/span&gt;&lt;/tt&gt;), floating point numbers (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;parse_float&lt;/span&gt;&lt;/tt&gt;), and constants (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;parse_constant&lt;/span&gt;&lt;/tt&gt;).&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="encoder-and-decoder-classes"&gt;&lt;br /&gt;&lt;h2&gt;Encoder and Decoder Classes&lt;/h2&gt;&lt;p&gt;Besides the convenience functions we have already examined, the &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/tt&gt; module provides classes for encoding and decoding.  By using the classes directly, you have access to extra APIs and can create subclasses to customize their behavior.&lt;/p&gt;&lt;p&gt;The JSONEncoder provides an iterable interface for producing &amp;#8220;chunks&amp;#8221; of encoded data, making it easier for you to write to files or network sockets without having to represent an entire data structure in memory.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;encoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONEncoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iterencode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;PART:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;As you can see, the output is generated in logical units, rather than being based on any size value.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_encoder_iterable.py&lt;br /&gt;PART: [&lt;br /&gt;PART: {&lt;br /&gt;PART: "a"&lt;br /&gt;PART: :&lt;br /&gt;PART: "A"&lt;br /&gt;PART: ,&lt;br /&gt;PART: "c"&lt;br /&gt;PART: :&lt;br /&gt;PART: 3.0&lt;br /&gt;PART: ,&lt;br /&gt;PART: "b"&lt;br /&gt;PART: :&lt;br /&gt;PART: [&lt;br /&gt;PART: 2&lt;br /&gt;PART: ,&lt;br /&gt;PART: 4&lt;br /&gt;PART: ]&lt;br /&gt;PART: }&lt;br /&gt;PART: ]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;encode()&lt;/span&gt;&lt;/tt&gt; method is basically equivalent to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;''.join(encoder.iterencode())&lt;/span&gt;&lt;/tt&gt;, with some extra error checking up front.&lt;/p&gt;&lt;p&gt;To encode arbitrary objects, we can override the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;default()&lt;/span&gt;&lt;/tt&gt; method with an implementation similar to what we used above in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;convert_to_builtin_type()&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json_myobj&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONEncoder&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;default(&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;)&amp;#39;&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Convert objects to a dictionary of their representation&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__class__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__class__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;br /&gt;              &lt;span class="s"&gt;&amp;#39;__module__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__module__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;              &lt;span class="p"&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json_myobj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MyObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;internal data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;MyEncoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The output is the same as the previous implementation.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_encoder_default.py&lt;br /&gt;&amp;lt;MyObj(internal data)&amp;gt;&lt;br /&gt;default( &amp;lt;MyObj(internal data)&amp;gt; )&lt;br /&gt;{"s": "internal data", "__module__": "json_myobj", "__class__": "MyObj"}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Decoding text, then converting the dictionary into an object takes a little more work to set up than our previous implementation, but not much.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecoder&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;object_hook&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dict_to_object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dict_to_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__class__&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;class_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;__class__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;module_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;__module__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;__import__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;MODULE:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;class_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;CLASS:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;ascii&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;INSTANCE ARGS:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;inst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;inst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;inst&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;encoded_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;[{&amp;quot;s&amp;quot;: &amp;quot;instance value goes here&amp;quot;, &amp;quot;__module__&amp;quot;: &amp;quot;json_myobj&amp;quot;, &amp;quot;__class__&amp;quot;: &amp;quot;MyObj&amp;quot;}]&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;myobj_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyDecoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoded_object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;myobj_instance&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;And the output is the same as the earlier example.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_decoder_object_hook.py&lt;br /&gt;MODULE: &amp;lt;module 'json_myobj' from '/Users/dhellmann/Documents/PyMOTW/src/PyMOTW/json/json_myobj.pyc'&amp;gt;&lt;br /&gt;CLASS: &amp;lt;class 'json_myobj.MyObj'&amp;gt;&lt;br /&gt;INSTANCE ARGS: {'s': u'instance value goes here'}&lt;br /&gt;[&amp;lt;MyObj(instance value goes here)&amp;gt;]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="working-with-streams-and-files"&gt;&lt;h2&gt;Working with Streams and Files&lt;/h2&gt;&lt;p&gt;In all of the examples so far, we have assumed that we could (and should) hold the encoded version of the entire data structure in memory at one time.  With large data structures it may be preferable to write the encoding directly to a file-like object.  The convenience functions &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;load()&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;dump()&lt;/span&gt;&lt;/tt&gt; accept references to a file-like object to use for reading or writing.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tempfile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamedTemporaryFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;w+&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;A socket would work in much the same way as the normal file handle used here.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_dump_file.py&lt;br /&gt;[{"a": "A", "c": 3.0, "b": [2, 4]}]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Although it isn&amp;#8217;t optimized to read only part of the data at a time, the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;load()&lt;/span&gt;&lt;/tt&gt; function still offers the benefit of encapsulating the logic of generating objects from stream input.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tempfile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamedTemporaryFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;w+&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;[{&amp;quot;a&amp;quot;: &amp;quot;A&amp;quot;, &amp;quot;c&amp;quot;: 3.0, &amp;quot;b&amp;quot;: [2, 4]}]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_load_file.py&lt;br /&gt;[{u'a': u'A', u'c': 3.0, u'b': [2, 4]}]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="mixed-data-streams"&gt;&lt;h2&gt;Mixed Data Streams&lt;/h2&gt;&lt;p&gt;The JSONDecoder includes the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;raw_decode()&lt;/span&gt;&lt;/tt&gt; method for decoding a data structure followed by more data, such as JSON data with trailing text.  The return value is the object created by decoding the input data, and an index into that data indicating where decoding left off.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;decoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_decoded_and_remainder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;encoded_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;[{&amp;quot;a&amp;quot;: &amp;quot;A&amp;quot;, &amp;quot;c&amp;quot;: 3.0, &amp;quot;b&amp;quot;: [2, 4]}]&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;extra_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;This text is not JSON.&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;JSON first:&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_decoded_and_remainder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;encoded_object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extra_text&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Object              :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;End of parsed input :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Remaining text      :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remaining&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;JSON embedded:&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_decoded_and_remainder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;br /&gt;        &lt;span class="s"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;extra_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoded_object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extra_text&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, this only works if the object appears at the beginning of the input.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python json_mixed_data.py&lt;br /&gt;JSON first:&lt;br /&gt;Object              : [{u'a': u'A', u'c': 3.0, u'b': [2, 4]}]&lt;br /&gt;End of parsed input : 35&lt;br /&gt;Remaining text      : ' This text is not JSON.'&lt;br /&gt;&lt;br /&gt;JSON embedded:&lt;br /&gt;ERROR: No JSON object could be decoded&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/json.html"&gt;json&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for this module.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://json.org/"&gt;http://json.org/&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;JavaScript Object Notation (JSON)&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://code.google.com/p/simplejson/"&gt;http://code.google.com/p/simplejson/&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;simplejson, from Bob Ippolito, et al, is the externally maintained development version of the json library included with Python 2.6 and Python 3.0. It maintains backwards compatibility with Python 2.4 and Python 2.5.&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The &lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/json/"&gt;canonical version&lt;/a&gt; of this article&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-5986814553367627571?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/5986814553367627571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=5986814553367627571' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/5986814553367627571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/5986814553367627571'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/05/pymotw-json.html' title='PyMOTW: json'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-4640878210286149147</id><published>2009-05-24T11:36:00.001-04:00</published><updated>2009-05-24T11:36:16.755-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>The Case for Working With Your Hands - NYTimes.com</title><content type='html'>&lt;p&gt;&lt;a href="http://www.nytimes.com/2009/05/24/magazine/24labor-t.html?pagewanted=1"&gt;The Case for Working With Your Hands - NYTimes.com&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Some diagnostic situations contain a lot of variables. Any given symptom may have several possible causes, and further, these causes may interact with one another and therefore be difficult to isolate. In deciding how to proceed, there often comes a point where you have to step back and get a larger gestalt. Have a cigarette and walk around the lift. The gap between theory and practice stretches out in front of you, and this is where it gets interesting. What you need now is the kind of judgment that arises only from experience; hunches rather than rules. For me, at least, there is more real thinking going on in the bike shop than there was in the think tank.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Although I like this article, and understand the source of Mr. Crawford's frustration with corporate culture, I have to take some exception with the categorization of all "knowledge work" as less honest than trade work.  The quote above, for example, could just as easily apply to software as motorcycles.  &lt;br /&gt;&lt;br /&gt;I've spent the last several weeks at work completely refactoring a major aspect of our application because we had finally reached the end of the long blind alley the existing design lead us to follow (it lasted us 7 years, so it was more like a blind turnpike).  As I worked my way back out onto the main road and found the right direction to take, I broke and re-fixed several ancillary features, wandered off path myself a few times, and spent a lot of time pondering the variables involved and how they interact.  &lt;br /&gt;&lt;br /&gt;The resulting design is proving to be more malleable and simpler to test, and as a result of both of those aspects it is vastly easier to maintain.  That's a big win for us, since even though I didn't add any customer-visible features to it in this release, by making the code easier to modify I was able to find and fix a major race condition.  The redesign also lays the groundwork for future planned enhancements.&lt;br /&gt;&lt;br /&gt;That's all by way of saying that working with your hands is honorable, but so can be working with your mind.  Just because companies like the abstracting service described in the article do a half-assed job of their work, that doesn't automatically mean all companies do.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-4640878210286149147?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/4640878210286149147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=4640878210286149147' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/4640878210286149147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/4640878210286149147'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/05/case-for-working-with-your-hands.html' title='The Case for Working With Your Hands - NYTimes.com'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-3858839206773586932</id><published>2009-04-28T08:13:00.001-04:00</published><updated>2009-04-28T08:13:35.655-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>Implementing MapReduce with multiprocessing</title><content type='html'>&lt;div class="section" id="implementing-mapreduce-with-multiprocessing"&gt;&lt;h1&gt;Implementing MapReduce with multiprocessing&lt;/h1&gt;&lt;p&gt;&lt;i&gt;While looking for example applications for Python's multiiprocessing module to use in this week's PyMOTW, someone suggested implementing MapReduce. Below is the simple implementation I came up with (the source is included in the PyMOTW tarball as of version 1.89).&lt;/i&gt;&lt;/p&gt;&lt;p&gt;The Pool class can be used to create a simple single-server MapReduce implementation.  Although it does not give the full benefits of distributed processing, it does illustrate how easy it is to break some problems down into distributable units of work.&lt;/p&gt;&lt;div class="section" id="simplemapreduce"&gt;&lt;h2&gt;SimpleMapReduce&lt;/h2&gt;&lt;p&gt;In MapReduce, input data is broken down into chunks for processing by different worker instances.  Each chunk of input data is &lt;em&gt;mapped&lt;/em&gt; to an intermediate state using a simple transformation.  The intermediate data is then collected together and partitioned based on a key value so that all of the related values are together.  Finally, the partitioned data is &lt;em&gt;reduced&lt;/em&gt; to a result set.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;collections&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleMapReduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;map_func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reduce_func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        map_func&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="sd"&gt;          Function to map inputs to intermediate data. Takes as argument one input value and&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;          returns a tuple with the key and a value to be reduced.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        reduce_func&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;          Function to reduce partitioned version of intermediate data to final output. Takes&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;          as argument a key as produced by map_func and a sequence of the values associated&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;          with that key.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;         &lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        num_workers&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;          The number of workers to create in the pool. Defaults to the number of CPUs&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;          available on the current host.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map_func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map_func&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce_func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reduce_func&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_workers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mapped_values&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Organize the mapped values by their key.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        Returns a dictionary mapping each key to a sequence of values.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;partitioned_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sublist&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mapped_values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sublist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;partitioned_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;partitioned_data&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__call__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunksize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Process the inputs through the map and reduce functions given.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        inputs&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;          An iterable containing the input data to be processed.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        chunksize=1&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;          The portion of the input data to hand to each worker.  This&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;          can be used to tune performance during the mapping phase.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;mapped_values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map_func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunksize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;chunksize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;partitioned_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mapped_values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;reduced_values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce_func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;partitioned_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;reduced_values&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="counting-words-in-files"&gt;&lt;h2&gt;Counting Words in Files&lt;/h2&gt;&lt;p&gt;The following example script uses SimpleMapReduce to counts the &amp;#8220;words&amp;#8221; in the reStructuredText source for this article, ignoring some of the markup.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing_mapreduce&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleMapReduce&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;file_to_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Read a file and return a sequence of (word, occurances) values.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;STOP_WORDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;br /&gt;        &lt;span class="s"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;an&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;and&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;are&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;as&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;be&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;for&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;if&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;in&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;br /&gt;        &lt;span class="s"&gt;&amp;#39;is&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;it&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;of&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;or&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;py&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rst&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;the&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;to&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;with&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;])&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;TR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maketrans&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;punctuation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;punctuation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;reading&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lstrip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;..&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c"&gt;# Skip rst comment lines&lt;/span&gt;&lt;br /&gt;                &lt;span class="k"&gt;continue&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# Strip punctuation&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isalpha&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;STOP_WORDS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;                    &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Convert the partitioned data for a word to a&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    tuple containing the word and the number of occurances.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;occurances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;occurances&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;operator&lt;/span&gt;&lt;br /&gt;    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;glob&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;input_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;*.rst&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;mapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleMapReduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_to_words&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count_words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;word_counts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;word_counts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;itemgetter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;word_counts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;TOP 20 WORDS BY FREQUENCY&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;top20&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;word_counts&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mf"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;longest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;top20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;top20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%-*s&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;%5s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;longest&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Each input filename is converted to a sequence of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;(word,&lt;/span&gt; &lt;span class="pre"&gt;1)&lt;/span&gt;&lt;/tt&gt; pairs by &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;file_to_words&lt;/span&gt;&lt;/tt&gt;.  The data is partitioned by &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;SimpleMapReduce.partition()&lt;/span&gt;&lt;/tt&gt; using the word as the key, so the partitioned data consists of a key and a sequence of 1 values representing the number of occurrences of the word.  The reduction phase converts that to a pair of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;(word,&lt;/span&gt; &lt;span class="pre"&gt;count)&lt;/span&gt;&lt;/tt&gt; values by calling &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;count_words&lt;/span&gt;&lt;/tt&gt; for each element of the partitioned data set.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_wordcount.py&lt;br /&gt;PoolWorker-1 reading communication.rst&lt;br /&gt;PoolWorker-1 reading index.rst&lt;br /&gt;PoolWorker-1 reading mapreduce.rst&lt;br /&gt;PoolWorker-2 reading basics.rst&lt;br /&gt;&lt;br /&gt;TOP 20 WORDS BY FREQUENCY&lt;br /&gt;&lt;br /&gt;process         :    74&lt;br /&gt;multiprocessing :    42&lt;br /&gt;worker          :    35&lt;br /&gt;after           :    31&lt;br /&gt;running         :    30&lt;br /&gt;start           :    29&lt;br /&gt;python          :    28&lt;br /&gt;processes       :    27&lt;br /&gt;literal         :    26&lt;br /&gt;header          :    26&lt;br /&gt;pymotw          :    26&lt;br /&gt;end             :    26&lt;br /&gt;daemon          :    23&lt;br /&gt;now             :    22&lt;br /&gt;consumer        :    20&lt;br /&gt;starting        :    18&lt;br /&gt;exiting         :    17&lt;br /&gt;event           :    16&lt;br /&gt;that            :    16&lt;br /&gt;by              :    15&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://en.wikipedia.org/wiki/MapReduce"&gt;MapReduce - Wikipedia&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;Overview of MapReduce on Wikipedia.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://labs.google.com/papers/mapreduce.html"&gt;MapReduce: Simplified Data Processing on Large Clusters&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;Google Labs presentation and paper on MapReduce.&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Special thanks to Jesse Noller for helping review this information.&lt;/em&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-3858839206773586932?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/3858839206773586932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=3858839206773586932' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3858839206773586932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3858839206773586932'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/04/implementing-mapreduce-with.html' title='Implementing MapReduce with multiprocessing'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-3596934198114985802</id><published>2009-04-28T08:03:00.001-04:00</published><updated>2009-04-28T08:03:48.364-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>PyMOTW: multiprocessing, part 2</title><content type='html'>&lt;div class="section" id="communication-between-processes-with-multiprocessing"&gt;&lt;h1&gt;Communication between processes with multiprocessing&lt;/h1&gt;&lt;p&gt;&lt;i&gt;This is part 2 of coverage of the multiprocessing module.  If you missed &lt;a href="http://blog.doughellmann.com/2009/04/pymotw-multiprocessing-part-1.html"&gt;part one&lt;/a&gt;, you may want to start there.&lt;/i&gt;&lt;/p&gt;&lt;div class="section" id="passing-messages-to-processes"&gt;&lt;br /&gt;&lt;span id="multiprocessing-queues"&gt;&lt;/span&gt;&lt;h2&gt;Passing Messages to Processes&lt;/h2&gt;&lt;p&gt;As with threads, a common use pattern for multiple processes is to divide a job up among several workers to run in parallel.  A simple way to do that with &lt;a title="Manage processes like threads." class="reference external" href="index.html#module-multiprocessing"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt; is to use Queues to pass messages back and forth.  Any pickle-able object can pass through a &lt;a title="Manage processes like threads." class="reference external" href="index.html#module-multiprocessing"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt; Queue.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFancyClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;proc_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Doing something fancy in &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; for &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;!&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proc_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyFancyClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Fancy Dan&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="c"&gt;# Wait for the worker to finish&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join_thread&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This short example only passes a single message to a single worker, then the main process waits for the worker to finish.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_queue.py&lt;br /&gt;Doing something fancy in Process-1 for Fancy Dan!&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;A more complex example shows how to manage several workers consuming data from the queue and passing results back to the parent process.  The &lt;em&gt;poison pill&lt;/em&gt; technique is used to stop the workers.  After setting up the real tasks, the main program adds one &amp;#8220;stop&amp;#8221; value per worker to the job queue.  When a worker encounters the special value, it breaks out of its processing loop.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task_queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result_queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task_queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;task_queue&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result_queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result_queue&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;proc_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;next_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task_queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;next_task&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class="c"&gt;# Poison pill means we should exit&lt;/span&gt;&lt;br /&gt;                &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;: Exiting&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;proc_name&lt;/span&gt;&lt;br /&gt;                &lt;span class="k"&gt;break&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proc_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_task&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result_queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__call__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# pretend to take some time to do our work&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; * &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; = &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; * &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="c"&gt;# Establish communication queues&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="c"&gt;# Start consumers&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;num_consumers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cpu_count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Creating &lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt; consumers&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;num_consumers&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;consumers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;Consumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_consumers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;consumers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="c"&gt;# Enqueue jobs&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;num_jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;10&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_jobs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="c"&gt;# Add a poison pill for each consumer&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_consumers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="c"&gt;# Start printing results&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;num_jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Result:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;num_jobs&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mf"&gt;1&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Although the jobs enter the queue in order, since their execution is parallelized there is no guarantee about the order they will be completed.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_producer_consumer.py&lt;br /&gt;Creating 4 consumers&lt;br /&gt;Consumer-4: 3 * 3&lt;br /&gt;Consumer-4: 7 * 7&lt;br /&gt;Consumer-4: Exiting&lt;br /&gt;Consumer-2: 1 * 1&lt;br /&gt;Consumer-2: 6 * 6&lt;br /&gt;Consumer-2: Exiting&lt;br /&gt;Consumer-3: 0 * 0&lt;br /&gt;Consumer-3: 5 * 5&lt;br /&gt;Consumer-3: 8 * 8&lt;br /&gt;Consumer-3: Exiting&lt;br /&gt;Consumer-1: 2 * 2&lt;br /&gt;Consumer-1: 4 * 4&lt;br /&gt;Consumer-1: 9 * 9&lt;br /&gt;Consumer-1: Exiting&lt;br /&gt;Result: 0 * 0 = 0&lt;br /&gt;Result: 1 * 1 = 1&lt;br /&gt;Result: 2 * 2 = 4&lt;br /&gt;Result: 3 * 3 = 9&lt;br /&gt;Result: 5 * 5 = 25&lt;br /&gt;Result: 4 * 4 = 16&lt;br /&gt;Result: 6 * 6 = 36&lt;br /&gt;Result: 7 * 7 = 49&lt;br /&gt;Result: 8 * 8 = 64&lt;br /&gt;Result: 9 * 9 = 81&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="signaling-between-processes-with-event-objects"&gt;&lt;h2&gt;Signaling between Processes with Event objects&lt;/h2&gt;&lt;p&gt;Events provide a simple way to communicate state information between processes.  An event can be toggled between set and unset states.  Users of the event object can wait for it to change from unset to set, using an optional timeout value.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wait_for_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Wait for the event to be set before doing anything&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;wait_for_event: starting&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;wait_for_event: e.is_set()-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wait_for_event_timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Wait t seconds and then timeout&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;wait_for_event_timeout: starting&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;wait_for_event_timeout: e.is_set()-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;w1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;block&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;br /&gt;                                 &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;wait_for_event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;                                 &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;w1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;w2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;non-block&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;br /&gt;                                 &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;wait_for_event_timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;br /&gt;                                 &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;w2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;main: waiting before calling Event.set()&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;main: event is set&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;When &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;wait()&lt;/span&gt;&lt;/tt&gt; times out it returns without an error.  The caller is responsible for checking the state of the event using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;is_set()&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_event.py&lt;br /&gt;wait_for_event_timeout: starting&lt;br /&gt;wait_for_event_timeout: e.is_set()-&amp;gt; False&lt;br /&gt;wait_for_event: starting&lt;br /&gt;wait_for_event: e.is_set()-&amp;gt; True&lt;br /&gt;main: waiting before calling Event.set()&lt;br /&gt;main: event is set&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="controlling-access-to-resources-with-lock"&gt;&lt;h2&gt;Controlling access to resources with Lock&lt;/h2&gt;&lt;p&gt;In situations when a single resource needs to be shared between multiple processes, a Lock can be used to avoid conflicting accesses.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Lock acquired via with&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker_no_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;acquire&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Lock acquired directly&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker_with&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;nw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker_no_with&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;nw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;nw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In this example, the messages printed to stdout may be jumbled together if the two processes do not synchronize their access of the output stream with the lock.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_lock.py&lt;br /&gt;Lock acquired via with&lt;br /&gt;Lock acquired directly&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="synchronizing-threads-with-a-condition-object"&gt;&lt;h2&gt;Synchronizing threads with a Condition object&lt;/h2&gt;&lt;p&gt;Condition objects let you synchronize parts of a workflow so that some run in parallel but others run sequentially, even if they are in separate processes.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stage_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;perform first stage of work, then notify stage_2 to continue&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; done and ready for stage 2&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notify_all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stage_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;wait for the condition telling us stage_1 is done&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; running&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Condition&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;s1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;stage_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;s2_clients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;stage_2[&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;]&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;stage_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;s2_clients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;s2_clients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In this example, two process run stage two of a job in parallel once the first stage is done.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_condition.py&lt;br /&gt;Starting s1&lt;br /&gt;s1 done and ready for stage 2&lt;br /&gt;Starting stage_2[1]&lt;br /&gt;stage_2[1] running&lt;br /&gt;Starting stage_2[2]&lt;br /&gt;stage_2[2] running&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="controlling-concurrent-access-to-resources-with-a-semaphore"&gt;&lt;h2&gt;Controlling concurrent access to resources with a Semaphore&lt;/h2&gt;&lt;p&gt;Sometimes it is useful to allow more than one worker access to a resource at a time,&lt;br /&gt;while still limiting the overall number. For example, a connection pool might&lt;br /&gt;support a fixed number of simultaneous connections, or a network application&lt;br /&gt;might support a fixed number of concurrent downloads. A Semaphore is one way&lt;br /&gt;to manage those connections.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActivePool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ActivePool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mgr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mgr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;makeActive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;makeInactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;makeActive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Now running: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;makeInactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ActivePool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Semaphore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Now running: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In this example, the ActivePool class simply serves as a convenient way to&lt;br /&gt;track which process are running at a given moment. A real resource pool&lt;br /&gt;would probably allocate a connection or some other value to the newly active&lt;br /&gt;process, and reclaim the value when the task is done. Here, it is just used to&lt;br /&gt;hold the names of the active processes to show that only 3 are running&lt;br /&gt;concurrently.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_semaphore.py&lt;br /&gt;Now running: ['3', '2', '0']&lt;br /&gt;Now running: ['3', '2', '0']&lt;br /&gt;Now running: ['0', '1', '5']&lt;br /&gt;Now running: ['2', '0', '1']&lt;br /&gt;Now running: ['0', '1', '4']&lt;br /&gt;Now running: ['3', '2', '0']&lt;br /&gt;Now running: ['0', '7', '6']&lt;br /&gt;Now running: ['0', '4', '7']&lt;br /&gt;Now running: ['7', '6', '8']&lt;br /&gt;Now running: ['7', '8', '9']&lt;br /&gt;Now running: ['7', '6', '8']&lt;br /&gt;Now running: ['7', '6', '8']&lt;br /&gt;Now running: ['7', '6', '8']&lt;br /&gt;Now running: ['7', '6', '8']&lt;br /&gt;Now running: ['7', '6', '8']&lt;br /&gt;Now running: ['7', '6', '8']&lt;br /&gt;Now running: ['7', '8', '9']&lt;br /&gt;Now running: ['8', '9']&lt;br /&gt;Now running: ['9']&lt;br /&gt;Now running: []&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="managers"&gt;&lt;h2&gt;Managers&lt;/h2&gt;&lt;p&gt;In the previous example, the list of active processes is maintained centrally in the ActivePool instance via a special type of list object created by a Manager.  The Manager is responsible for coordinating shared information state between all of its users.  By creating the list through the manager, the list is updated in all processes when anyone modifies it.  In addition to lists, dictionaries are also supported.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;mgr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mgr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;             &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;br /&gt;             &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Results:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_manager_dict.py&lt;br /&gt;Results: {0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="namespaces"&gt;&lt;h2&gt;Namespaces&lt;/h2&gt;&lt;p&gt;In addition to dictionaries and lists, a Manager can create a shared Namespace.  Any named value added to the Namespace is visible across all of the clients.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;This is the value&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Before event, consumer got:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;After event, consumer got:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;mgr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mgr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_namespaces.py&lt;br /&gt;Before event, consumer got: 'Namespace' object has no attribute 'value'&lt;br /&gt;After event, consumer got: This is the value&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;It is important to know that &lt;em&gt;updates&lt;/em&gt; to mutable values in the namespace are &lt;em&gt;not&lt;/em&gt; propagated.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;my_list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;This is the value&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# DOES NOT UPDATE GLOBAL VALUE!&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Before event, consumer got:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;my_list&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;After event, consumer got:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;my_list&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;mgr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mgr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;my_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_namespaces_mutable.py&lt;br /&gt;Before event, consumer got: []&lt;br /&gt;After event, consumer got: []&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="pool-map"&gt;&lt;h2&gt;Pool.map&lt;/h2&gt;&lt;p&gt;For simple cases where the work to be done can be broken up and distributed between workers, you do not have to manage the queue and worker processes yourself.  The Pool class maintains a fixed number of workers and passes them jobs.  The return values are collected and returned as a list.  The result is functionally equivalent to the built-in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;map()&lt;/span&gt;&lt;/tt&gt;, except that individual tasks run in parallel.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_calculation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;pool_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cpu_count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pool_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Input   :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;builtin_outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;do_calculation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Built-in:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;builtin_outputs&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;pool_outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;do_calculation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Pool    :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool_outputs&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_pool.py&lt;br /&gt;Input   : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]&lt;br /&gt;Built-in: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]&lt;br /&gt;Pool    : [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-3596934198114985802?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/3596934198114985802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=3596934198114985802' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3596934198114985802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3596934198114985802'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/04/pymotw-multiprocessing-part-2.html' title='PyMOTW: multiprocessing, part 2'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-6368045911440149473</id><published>2009-04-19T12:52:00.001-04:00</published><updated>2009-04-19T13:23:04.240-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>PyMOTW: multiprocessing, part 1</title><content type='html'>&lt;div class="section" id="multiprocessing-basics"&gt;&lt;h1&gt;&lt;a title="Manage processes like threads." class="reference external" href="index.html#module-multiprocessing"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt; Basics&lt;/h1&gt;&lt;table class="docutils field-list" frame="void" rules="none"&gt;&lt;col class="field-name"&gt;&lt;/col&gt;&lt;col class="field-body"&gt;&lt;/col&gt;&lt;tbody valign="top"&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Purpose:&lt;/th&gt;&lt;td class="field-body"&gt;Provides an API for managing processes.&lt;/td&gt;&lt;/tr&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Python Version:&lt;/th&gt;&lt;td class="field-body"&gt;2.6&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;The multiprocessing module includes a relatively simple API for dividing work up between multiple processes.  It is based on the API for &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/tt&gt;, and in some cases is a drop-in replacement.  Due to the similarity, the first few examples here are modified from the threading examples.  Features provided by multiprocessing but not available in threading are covered later.&lt;/p&gt;&lt;div class="section" id="process-objects"&gt;&lt;h2&gt;Process objects&lt;/h2&gt;&lt;p&gt;The simplest way to use a sub-process is to instantiate it with a target function&lt;br /&gt;and call start() to let it begin working.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;worker function&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Worker&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The output includes the word &amp;#8220;Worker&amp;#8221; printed five times, although it may not be entirely clean depending on the order of execution.  A later example illustrates using a lock to ensure that only one worker can print to stdout at a time.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_simple.py&lt;br /&gt;Worker&lt;br /&gt;Worker&lt;br /&gt;Worker&lt;br /&gt;Worker&lt;br /&gt;Worker&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;It usually more useful to be able to spawn a process with arguments to tell it what&lt;br /&gt;work to do.  Unlike with &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/tt&gt;, to pass arguments to a &lt;a title="Manage processes like threads." class="reference external" href="index.html#module-multiprocessing"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt; Process the argument must be able to be pickled.  As a simple example we could pass each&lt;br /&gt;worker a number so the output is a little more interesting in the second&lt;br /&gt;example.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;thread worker function&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Worker:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The integer argument is now included in the message printed by each worker:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_simpleargs.py&lt;br /&gt;Worker: 0&lt;br /&gt;Worker: 1&lt;br /&gt;Worker: 2&lt;br /&gt;Worker: 3&lt;br /&gt;Worker: 4&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="importable-target-functions"&gt;&lt;h2&gt;Importable Target Functions&lt;/h2&gt;&lt;p&gt;One difference you will notice between the &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/tt&gt; and &lt;a title="Manage processes like threads." class="reference external" href="index.html#module-multiprocessing"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt; examples is the extra protection for &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;__main__&lt;/span&gt;&lt;/tt&gt; used here.  Due to the way the new processes are started, the child process needs to be able to import the script containing the target function.  In these examples I accomplish that by wrapping the main part of the application so it is not run recursively in each child.  You could also import the target function from a separate script.&lt;/p&gt;&lt;p&gt;For example, this main program:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing_import_worker&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;multiprocessing_import_worker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;uses this worker function, defined in a separate module:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;worker function&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Worker&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;and produces output like the first example above:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_import_main.py&lt;br /&gt;Worker&lt;br /&gt;Worker&lt;br /&gt;Worker&lt;br /&gt;Worker&lt;br /&gt;Worker&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="determining-the-current-process"&gt;&lt;h2&gt;Determining the Current Process&lt;/h2&gt;&lt;p&gt;Passing arguments to identify or name the process is cumbersome, and unnecessary.&lt;br /&gt;Each Process instance has a name with a default value that you can change as&lt;br /&gt;the process is created. Naming processes is useful if you have a server&lt;br /&gt;with multiple service children handling different operations.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_service&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;my_service&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;my_service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;worker_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;worker 1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;worker_2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# use default name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;worker_1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;worker_2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The debug output includes the name of the current process on each line. The&lt;br /&gt;lines with &amp;#8220;Process-3&amp;#8221; in the name column correspond to the unnamed&lt;br /&gt;process w2.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_names.py&lt;br /&gt;worker 1 Starting&lt;br /&gt;worker 1 Exiting&lt;br /&gt;Process-3 Starting&lt;br /&gt;Process-3 Exiting&lt;br /&gt;my_service Starting&lt;br /&gt;my_service Exiting&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="daemon-processes"&gt;&lt;br /&gt;&lt;h2&gt;Daemon Processes&lt;/h2&gt;&lt;p&gt;By default the main program will not exit until all of the children have exited. There are&lt;br /&gt;times when you want to start a background process and let it run without blocking the main&lt;br /&gt;program from exiting. Using daemon processes like this is useful for services where there may&lt;br /&gt;not be an easy way to interrupt the worker or where letting it die in the middle of its work&lt;br /&gt;does not lose or corrupt data (for example, a task that generates &amp;#8220;heart beats&amp;#8221; for a service&lt;br /&gt;monitoring tool). To mark a process as a daemon, set its &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;daemon&lt;/span&gt;&lt;/tt&gt; attribute with a boolean&lt;br /&gt;value. The default is for processes to not be daemons, so passing True turns the daemon mode&lt;br /&gt;on.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;daemon&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;non_daemon&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;daemon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;non-daemon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;non_daemon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Notice that the output does not include the &amp;#8220;Exiting&amp;#8221; message from the daemon&lt;br /&gt;process, since all of the non-daemon processes (including the main program) exit&lt;br /&gt;before the daemon process wakes up from its 2 second sleep.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_daemon.py&lt;br /&gt;Starting: non-daemon&lt;br /&gt;Exiting : non-daemon&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;The daemon process is terminated before the main program exits, to avoid leaving orphaned processes running.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="waiting-for-processes"&gt;&lt;br /&gt;&lt;h2&gt;Waiting for Processes&lt;/h2&gt;&lt;p&gt;To wait until a process has completed its work and exited, use the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;join()&lt;/span&gt;&lt;/tt&gt; method.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;daemon&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;non_daemon&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;daemon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;non-daemon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;non_daemon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Since we wait for the daemon to exit using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;join()&lt;/span&gt;&lt;/tt&gt;, we do see its&lt;br /&gt;&amp;#8220;Exiting&amp;#8221; message.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_daemon_join.py&lt;br /&gt;Starting: non-daemon&lt;br /&gt;Exiting : non-daemon&lt;br /&gt;Starting: daemon&lt;br /&gt;Exiting : daemon&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;By default, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;join()&lt;/span&gt;&lt;/tt&gt; blocks indefinitely. It is also possible to pass a timeout&lt;br /&gt;argument (a float representing the number of seconds to wait for the process to&lt;br /&gt;become inactive). If the process does not complete within the timeout period,&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;join()&lt;/span&gt;&lt;/tt&gt; returns anyway.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;daemon&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;non_daemon&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Exiting :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;daemon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;non-daemon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;non_daemon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;d.is_alive()&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_alive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Since the timeout passed is less than the amount of time the daemon&lt;br /&gt;sleeps, the process is still &amp;#8220;alive&amp;#8221; after &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;join()&lt;/span&gt;&lt;/tt&gt; returns.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_daemon_join_timeout.py&lt;br /&gt;Starting: non-daemon&lt;br /&gt;Exiting : non-daemon&lt;br /&gt;d.is_alive() True&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="terminating-processes"&gt;&lt;br /&gt;&lt;h2&gt;Terminating Processes&lt;/h2&gt;&lt;p&gt;Although it is better to use the &lt;em&gt;poison pill&lt;/em&gt; method of signaling to a process that it should exit, if a process appears hung or deadlocked it can be useful to be able to kill it forcibly.  Calling &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;terminate()&lt;/span&gt;&lt;/tt&gt; on a process object kills the child process.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow_worker&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting worker&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Finished worker&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;slow_worker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;BEFORE:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_alive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;DURING:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_alive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;TERMINATED:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_alive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;JOINED:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_alive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="admonition note"&gt;&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;&lt;p class="last"&gt;It is important to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;join()&lt;/span&gt;&lt;/tt&gt; the process after terminating it in order to give the background machinery time to update the status of the object to reflect the termination.&lt;/p&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_terminate.py&lt;br /&gt;BEFORE: &amp;lt;Process(Process-1, initial)&amp;gt; False&lt;br /&gt;DURING: &amp;lt;Process(Process-1, started)&amp;gt; True&lt;br /&gt;TERMINATED: &amp;lt;Process(Process-1, started)&amp;gt; True&lt;br /&gt;JOINED: &amp;lt;Process(Process-1, stopped[SIGTERM])&amp;gt; False&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="process-exit-status"&gt;&lt;h2&gt;Process Exit Status&lt;/h2&gt;&lt;p&gt;The status code produced when the process exits can be accessed via the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;exitcode&lt;/span&gt;&lt;/tt&gt; attribute.&lt;/p&gt;&lt;p&gt;For &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;exitcode&lt;/span&gt;&lt;/tt&gt; values&lt;/p&gt;&lt;br /&gt;&lt;ul class="simple"&gt;&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;==&lt;/span&gt; &lt;span class="pre"&gt;0&lt;/span&gt;&lt;/tt&gt; &amp;#8211; no error was produced&lt;/li&gt;&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;0&lt;/span&gt;&lt;/tt&gt; &amp;#8211; the process had an error, and exited with that code&lt;/li&gt;&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;lt;&lt;/span&gt; &lt;span class="pre"&gt;0&lt;/span&gt;&lt;/tt&gt; &amp;#8211; the process was killed with a signal of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-1&lt;/span&gt; &lt;span class="pre"&gt;*&lt;/span&gt; &lt;span class="pre"&gt;exitcode&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;exit_error&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;exit_ok&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;return_value&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;There was an error!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;terminated&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;exit_error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exit_ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;terminated&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Starting process for&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func_name&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;    &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;.exitcode = &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exitcode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Processes that raise an exception automatically get an &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;exitcode&lt;/span&gt;&lt;/tt&gt; of 1.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_exitcode.py&lt;br /&gt;Starting process for exit_error&lt;br /&gt;Starting process for exit_ok&lt;br /&gt;Starting process for return_value&lt;br /&gt;Starting process for raises&lt;br /&gt;Process raises:&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/multiprocessing/process.py", line 231, in _bootstrap&lt;br /&gt;    self.run()&lt;br /&gt;  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/multiprocessing/process.py", line 88, in run&lt;br /&gt;    self._target(*self._args, **self._kwargs)&lt;br /&gt;  File "multiprocessing_exitcode.py", line 24, in raises&lt;br /&gt;    raise RuntimeError('There was an error!')&lt;br /&gt;RuntimeError: There was an error!&lt;br /&gt;Starting process for terminated&lt;br /&gt;exit_error.exitcode = 1&lt;br /&gt;exit_ok.exitcode = 0&lt;br /&gt;return_value.exitcode = 0&lt;br /&gt;raises.exitcode = 1&lt;br /&gt;terminated.exitcode = -15&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="logging"&gt;&lt;h2&gt;Logging&lt;/h2&gt;&lt;p&gt;When debugging concurrency issues, it can be useful to have access to the internals of the objects provided by &lt;a title="Manage processes like threads." class="reference external" href="index.html#module-multiprocessing"&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;.  There is a convenient module-level function to enable logging called &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;log_to_stderr()&lt;/span&gt;&lt;/tt&gt;.  It sets up a logger object using &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;logging&lt;/span&gt;&lt;/tt&gt; and adds a handler so that log messages are sent to the standard error channel.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Doing some work&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log_to_stderr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;By default the logging level is set to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;NOTSET&lt;/span&gt;&lt;/tt&gt; so no messages are produced.  Pass a different level to initialize the logger to the level of detail you want.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_log_to_stderr.py&lt;br /&gt;[INFO/Process-1] child process calling self.run()&lt;br /&gt;Doing some work&lt;br /&gt;[INFO/Process-1] process shutting down&lt;br /&gt;[DEBUG/Process-1] running all "atexit" finalizers with priority &amp;gt;= 0&lt;br /&gt;[DEBUG/Process-1] running the remaining "atexit" finalizers&lt;br /&gt;[INFO/Process-1] process exiting with exitcode 0&lt;br /&gt;[INFO/MainProcess] process shutting down&lt;br /&gt;[DEBUG/MainProcess] running all "atexit" finalizers with priority &amp;gt;= 0&lt;br /&gt;[DEBUG/MainProcess] running the remaining "atexit" finalizers&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;To manipulate the logger directly (change its level setting or add handlers), use &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;get_logger()&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Doing some work&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log_to_stderr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The logger can also be configured through the &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;logging&lt;/span&gt;&lt;/tt&gt; configuration file API, using the name &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_get_logger.py&lt;br /&gt;[INFO/Process-1] child process calling self.run()&lt;br /&gt;Doing some work&lt;br /&gt;[INFO/Process-1] process shutting down&lt;br /&gt;[INFO/Process-1] process exiting with exitcode 0&lt;br /&gt;[INFO/MainProcess] process shutting down&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="subclassing-process"&gt;&lt;h2&gt;Subclassing Process&lt;/h2&gt;&lt;p&gt;Although the simplest way to start a job in a separate process is to use &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;Process&lt;/span&gt;&lt;/tt&gt; and pass a target function, it is also possible to use a custom subclass.  The derived class should override &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;run()&lt;/span&gt;&lt;/tt&gt; to do its work.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;In &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python multiprocessing_subclass.py&lt;br /&gt;In Worker-1&lt;br /&gt;In Worker-2&lt;br /&gt;In Worker-3&lt;br /&gt;In Worker-4&lt;br /&gt;In Worker-5&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/multiprocessing.html"&gt;multiprocessing&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for this module.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;High-level API for working with threads.&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-6368045911440149473?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/6368045911440149473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=6368045911440149473' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6368045911440149473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6368045911440149473'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/04/pymotw-multiprocessing-part-1.html' title='PyMOTW: multiprocessing, part 1'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-6763081779204063493</id><published>2009-04-06T10:01:00.001-04:00</published><updated>2009-04-06T10:01:11.594-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='usability'/><category scheme='http://www.blogger.com/atom/ns#' term='lifehack'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><title type='text'>Configuring Firefox so its Tab/Window Behavior isn't Annoying</title><content type='html'>I toggled a setting in Firefox a couple days ago and its tab/window behavior changed in a way that was exceptionally annoying.  It took me a while to to find the now-hidden settings (who removes options &lt;em&gt;only&lt;/em&gt; from the UI?) to reset the behavior, so I'm recording it here for next time.&lt;br /&gt;&lt;br /&gt;I want it to create a new window when an external app tells it to open a URL, and to use a tab when I click on a link that would open a new window from a page I'm already viewing (such as search results).  That prevents apps like Quicksilver from opening tabs in the "last active" window that happens to be on another Spaces desktop, but also doesn't clutter my screen with zillions of new windows as I browse.&lt;br /&gt;&lt;br /&gt;FF 3.0.8 for Mac OS X has an option to tell it whether to open new tabs or windows by default:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align:center;"&gt;&lt;img src="http://lh5.ggpht.com/_--Fv8pzwveE/SdoIuKzOU3I/AAAAAAAAALY/QbfVIyrUa48/firefox-tab-preferences.png?imgmax=800" alt="firefox-tab-preferences.png" border="0" width="408" height="260" /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It &lt;em&gt;used&lt;/em&gt; to have separate options for what to do when an external application asked for a URL to be opened vs. when you clicked on a link on a page.  I guess someone decided that was confusing.  This &lt;a href="http://reviews.cnet.com/4520-10165_7-6212515-1.html"&gt;Cnet article&lt;/a&gt; describes how to turn it on:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The options for this behavior are shown at the top of the Tabbed Browsing panel in the Preferences window. If you ever feel the need to set this preference via About:config, look for browser.link.open_external. Setting this preference to 1 opens the link in the current tab and window, 2 opens it in a new window, and 3 opens it in a new tab in the front window.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Along the way I found another semi-useful setting via &lt;a href="http://lifehacker.com/software/firefox/firefox-tip-open-search-results-in-a-new-tab-255171.php"&gt;Lifehacker&lt;/a&gt; that opens a new tab when you use the search box.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Type about:config into the address bar, and then put the following into the filter box: browser.search.openintab. Double-click the value to change it to true.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Now every search comes up in its own tab and I don't lose any open pages.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-6763081779204063493?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/6763081779204063493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=6763081779204063493' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6763081779204063493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6763081779204063493'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/04/configuring-firefox-so-its-tabwindow.html' title='Configuring Firefox so its Tab/Window Behavior isn&amp;#39;t Annoying'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-2389991885214587349</id><published>2009-04-05T13:19:00.001-04:00</published><updated>2009-04-05T13:19:14.827-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>PyMOTW: pipes</title><content type='html'>&lt;div class="section" id="module-pipes"&gt;&lt;h1&gt;pipes &amp;#8211; Unix shell command pipeline templates&lt;/h1&gt;&lt;table class="docutils field-list" frame="void" rules="none"&gt;&lt;col class="field-name"&gt;&lt;/col&gt;&lt;col class="field-body"&gt;&lt;/col&gt;&lt;tbody valign="top"&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Purpose:&lt;/th&gt;&lt;td class="field-body"&gt;Create repeatable Unix shell command pipelines.&lt;/td&gt;&lt;/tr&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Python Version:&lt;/th&gt;&lt;td class="field-body"&gt;Python 1.4&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;The &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;pipes&lt;/span&gt;&lt;/tt&gt; module implements a class to create arbitrarily complex Unix command pipelines.  Inputs and outputs of the commands can be chained together as with the shell &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;|&lt;/span&gt;&lt;/tt&gt; operator, even if the individual commands need to write to or read from files instead of stdin/stdout.&lt;/p&gt;&lt;div class="section" id="passing-standard-i-o-through-a-pipe"&gt;&lt;br /&gt;&lt;h2&gt;Passing Standard I/O Through a Pipe&lt;/h2&gt;&lt;p&gt;A very simple example, passing standard input through a pipe and receiving the results in a file looks like this:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pipes&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tempfile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Establish a very simple pipeline using stdio&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cat -&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Pass some text through the pipeline,&lt;/span&gt;&lt;br /&gt;&lt;span class="c"&gt;# saving the output to a temporary file.&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamedTemporaryFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Some text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Rewind and read the text written&lt;/span&gt;&lt;br /&gt;&lt;span class="c"&gt;# to the temporary file&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The pipeline Template is created and then a single command, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;cat&lt;/span&gt; &lt;span class="pre"&gt;-&lt;/span&gt;&lt;/tt&gt; is added.  The command reads standard input and writes it to standard output, without modification.  The second argument to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;append()&lt;/span&gt;&lt;/tt&gt; encodes the input and output sources for the command in two characters (input, then output).  Using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-&lt;/span&gt;&lt;/tt&gt; means the command uses standard I/O.  Using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;f&lt;/span&gt;&lt;/tt&gt; means the command needs to read from a file (as may be the case with an image processing pipeline).&lt;/p&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;debug()&lt;/span&gt;&lt;/tt&gt; method toggles debugging output on and off.  When debugging is enabled, the commands being run are printed and the shell is given &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;set&lt;/span&gt; &lt;span class="pre"&gt;-x&lt;/span&gt;&lt;/tt&gt; so it runs verbosely.&lt;/p&gt;&lt;p&gt;After the pipeline is set up, a NamedTemporaryFile is created to give the pipeline somewhere to write its output.  A file must always be specified as argument to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;open()&lt;/span&gt;&lt;/tt&gt;, whether reading or writing.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python pipes_simple_write.py&lt;br /&gt;+ cat -&lt;br /&gt;cat - &amp;gt;/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpeaa2Zz&lt;br /&gt;Some text&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Reading from a pipeline works basically the same way, with a few changes to the arguments.  For our example, we need to set up the contents of the input file before opening the pipline.  Then we can pass that filename as input to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;open()&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pipes&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tempfile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Establish a very simple pipeline using stdio&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cat -&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Establish an input file&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamedTemporaryFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Some text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Pass some text through the pipeline,&lt;/span&gt;&lt;br /&gt;&lt;span class="c"&gt;# saving the output to a temporary file.&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;We can read the results from the pipeline directly.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python pipes_simple_read.py&lt;br /&gt;+ cat -&lt;br /&gt;cat - &amp;lt;/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpiu1dGJ&lt;br /&gt;Some text&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="using-files-instead-of-streams"&gt;&lt;h2&gt;Using Files Instead of Streams&lt;/h2&gt;&lt;p&gt;Some commands need to work on files on the filesystem instead of input streams.  Commands that process a large amount of data might perform better in this mode, since they will not block on the next command reading their output.  Anything that works on non-stream-based data requires this capability as well (e.g., databases or other binary file manipulation tools).  To support this mode of operation, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;append()&lt;/span&gt;&lt;/tt&gt; lets you specify a &lt;em&gt;kind&lt;/em&gt; of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;f&lt;/span&gt;&lt;/tt&gt;, and the pipeline code will create the needed temporary files.  The filenames are passed to the shell as &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;$IN&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;$OUT&lt;/span&gt;&lt;/tt&gt;, so those variable names need to appear in your command string.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pipes&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tempfile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cat $IN &amp;gt; $OUT&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ff&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamedTemporaryFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Some text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;As you see, several intermediate temporary files are created to hold the input and output of the step.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python pipes_file_kind.py&lt;br /&gt;+ trap 'rm -f /var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmp13RgCk; exit' 1 2 3 13 14 15&lt;br /&gt;+ cat&lt;br /&gt;+ IN=/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmp13RgCk&lt;br /&gt;+ OUT=/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpvHbUr6&lt;br /&gt;+ cat /var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmp13RgCk&lt;br /&gt;+ rm -f /var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmp13RgCk&lt;br /&gt;trap 'rm -f /var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmp13RgCk; exit' 1 2 3 13 14 15&lt;br /&gt;cat &amp;gt;/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmp13RgCk&lt;br /&gt;IN=/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmp13RgCk; OUT=/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpvHbUr6; cat $IN &amp;gt; $OUT&lt;br /&gt;rm -f /var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmp13RgCk&lt;br /&gt;Some text&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;And of course the input and output &lt;em&gt;kind&lt;/em&gt; values can be mixed so that different steps of the pipeline use files or standard I/O as needed.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pipes&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tempfile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cat $IN&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;f-&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cat - &amp;gt; $OUT&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;-f&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamedTemporaryFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Some text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The trap statements visible in the output here ensure that the temporary files created by the pipeline are cleaned up even a task fails in the middle or the shell is killed.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python pipes_mixed_kinds.py&lt;br /&gt;+ trap 'rm -f /var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpsYkNeR; exit' 1 2 3 13 14 15&lt;br /&gt;+ cat&lt;br /&gt;+ IN=/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpsYkNeR&lt;br /&gt;+ cat /var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpsYkNeR&lt;br /&gt;+ OUT=/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmp3bffm3&lt;br /&gt;+ cat -&lt;br /&gt;+ rm -f /var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpsYkNeR&lt;br /&gt;trap 'rm -f /var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpsYkNeR; exit' 1 2 3 13 14 15&lt;br /&gt;cat &amp;gt;/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpsYkNeR&lt;br /&gt;IN=/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpsYkNeR; cat $IN |&lt;br /&gt;{ OUT=/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmp3bffm3; cat - &amp;gt; $OUT; }&lt;br /&gt;rm -f /var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpsYkNeR&lt;br /&gt;Some text&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="a-more-complex-example"&gt;&lt;h2&gt;A More Complex Example&lt;/h2&gt;&lt;p&gt;All of the examples up to this point have been fairly trivial.  They were constructed to illustrate how to use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;pipes.Template()&lt;/span&gt;&lt;/tt&gt; without depending on deep knowledge of shell scripting in general.  This example is more complex, and shows how several commands can be combined to manipulate data before bringing it into Python.&lt;/p&gt;&lt;p&gt;My &lt;a class="reference external" href="http://www.doughellmann.com/projects/virtualenvwrapper/"&gt;virtualenvwrapper&lt;/a&gt; script includes a shell function for listing all of the virtual environments you have created.  The function is used for tab-completion and can be used directly to list the environments, in case you forget a name.  The heart of that function is a small pipeline that looks in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;$WORKON_HOME&lt;/span&gt;&lt;/tt&gt; for directories that look like virtual environments (i.e., they have an &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;activate&lt;/span&gt;&lt;/tt&gt; script).  That pipeline is:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;(cd "$WORKON_HOME"; for f in */bin/activate; do echo $f; done) \&lt;br /&gt;    | sed 's|^\./||' \&lt;br /&gt;    | sed 's|/bin/activate||' \&lt;br /&gt;    | sort&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Implemented using &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;pipes&lt;/span&gt;&lt;/tt&gt;, the pipeline looks like:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pipes&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tempfile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cd &amp;quot;$WORKON_HOME&amp;quot;; for f in */bin/activate; do echo $f; done&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r&amp;quot;sed &amp;#39;s|^\./||&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sed &amp;#39;s|/bin/activate||&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;sort&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamedTemporaryFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;sandboxes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;SANDBOXES:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sandboxes&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Since each sandbox name is written to a separate line, parsing the output is easy:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python pipes_multistep.py&lt;br /&gt;SANDBOXES: ['CastSampler', 'blogbackup', 'docket', 'doughellmann', 'nose', 'personal', 'pymag', 'pymotw', 'pymotw25', 'pymotw26']&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="passing-files-through-pipelines"&gt;&lt;h2&gt;Passing Files Through Pipelines&lt;/h2&gt;&lt;p&gt;If the input to your pipeline already exists in a file on disk, there&amp;#8217;s no need to read it into Python simply to pass it to the pipeline.  You can use the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;copy()&lt;/span&gt;&lt;/tt&gt; method to pass the file directly through the pipeline and create an output file for reading.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pipes&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tempfile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;grep -n tortor $IN&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;f-&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamedTemporaryFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;lorem.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python pipes_copy.py&lt;br /&gt;+ IN=lorem.txt&lt;br /&gt;+ grep -n tortor lorem.txt&lt;br /&gt;IN=lorem.txt; grep -n tortor $IN &amp;gt;/var/folders/9R/9R1t+tR02Raxzk+F71Q50U+++Uw/-Tmp-/tmpibxIEG&lt;br /&gt;3:elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla&lt;br /&gt;6:lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas&lt;br /&gt;11:eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="cloning-templates"&gt;&lt;h2&gt;Cloning Templates&lt;/h2&gt;&lt;p&gt;Once you have a pipeline template, you may want to use it multiple times or create variants without re-constructing the entire object.  The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;clone()&lt;/span&gt;&lt;/tt&gt; method makes both of these operations easy.  This example constructs a simple word-counter pipeline, then prepends commands to a couple of clones to make it look for different words.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pipes&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tempfile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;count_word_substring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="c"&gt;#count_word_substring.debug(True)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;count_word_substring&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;grep -f - /usr/share/dict/words&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;count_word_substring&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;wc -l&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;count_py&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count_word_substring&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;count_py&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prepend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;echo &amp;quot;py&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count_py&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/dev/null&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;  &amp;quot;py&amp;quot;: &lt;/span&gt;&lt;span class="si"&gt;%5s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;count_perl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count_word_substring&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;count_perl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prepend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;echo &amp;quot;perl&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count_perl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/dev/null&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;quot;perl&amp;quot;: &lt;/span&gt;&lt;span class="si"&gt;%5s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;By prepending a custom command to each clone, we can create separate pipelines that perform the same basic function with small variations.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python pipes_clone.py&lt;br /&gt;  "py":  1379&lt;br /&gt;"perl":    71&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/pipes.html"&gt;pipes&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for this module.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;tempfile&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;The tempfile module includes classes for managing temporary files.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;subprocess&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;The subprocess module also supports chaining the inputs and outputs of processes together.&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-2389991885214587349?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/2389991885214587349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=2389991885214587349' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/2389991885214587349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/2389991885214587349'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/04/pymotw-pipes.html' title='PyMOTW: pipes'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-6820199350768279439</id><published>2009-03-24T08:18:00.001-04:00</published><updated>2009-03-24T10:37:13.007-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtualenvwrapper'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>virtualenvwrapper updates</title><content type='html'>The &lt;a href="http://www.doughellmann.com/projects/virtualenvwrapper/1.12/"&gt;latest version available for download is 1.12&lt;/a&gt;.  New features include pre and post operation hooks for operations involving virtualenvs (so you can do things like install your favorite common packages every time you make a new virtualenv), navigation functions for working inside the environment, and a host of fixes and optimizations. Check the &lt;a href="http://pypi.python.org/pypi/virtualenvwrapper"&gt;release log on PyPI&lt;/a&gt; for a complete history of the updates.&lt;br /&gt;&lt;br /&gt;In the ~2 weeks since I've &lt;a href="http://bitbucket.org/dhellmann/virtualenvwrapper/"&gt;uploaded virtualenvwrapper to bitbucket&lt;/a&gt;, I've received more patches than in all the previous time I maintained the script.  Score 1 for DVCS!&lt;br /&gt;&lt;br /&gt;[Updated: Changed "bitkeeper" to "bitbucket" - Sorry Jesper!]&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-6820199350768279439?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/6820199350768279439/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=6820199350768279439' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6820199350768279439'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/6820199350768279439'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/03/virtualenvwrapper-updates.html' title='virtualenvwrapper updates'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-3891926667288694667</id><published>2009-03-14T11:01:00.001-04:00</published><updated>2009-03-14T11:01:53.939-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DVCS'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>PyMOTW source now available on BitBucket.org</title><content type='html'>Earlier this week I uploaded all of the history for PyMOTW to &lt;a href="http://bitbucket.org/dhellmann/pymotw/"&gt;BitBucket.org&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;BitBucket uses Mercurial as its DVCS, and after a couple of hiccups with the initial conversion I've had pretty good luck.  I think I have the workflow down far managing local changes vs. updates pushed to the central repository.  &lt;br /&gt;&lt;br /&gt;I still need to work out how (and whether) to use branches.  I have a sense that I can use local clones in the way I used to use branches: starting an article that was going to take several sessions, without committing the changes to the trunk.  What are the typical practices for hg branching? Do people use them?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.doughellmann.com/2009/03/pymotw-asynchat.html"&gt;Today's PyMOTW post&lt;/a&gt; is the first post since the change-over.  If you encounter any problems, please report them as an issue via the BitBucket issue tracker.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-3891926667288694667?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/3891926667288694667/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=3891926667288694667' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3891926667288694667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/3891926667288694667'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/03/pymotw-source-now-available-on.html' title='PyMOTW source now available on BitBucket.org'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-8057260674891283712</id><published>2009-03-14T10:51:00.001-04:00</published><updated>2009-03-14T10:51:32.950-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='PyMOTW'/><title type='text'>PyMOTW: asynchat</title><content type='html'>&lt;div class="section" id="module-asynchat"&gt;&lt;h1&gt;asynchat &amp;#8211; Asynchronous protocol handler&lt;/h1&gt;&lt;table class="docutils field-list" frame="void" rules="none"&gt;&lt;col class="field-name"&gt;&lt;/col&gt;&lt;col class="field-body"&gt;&lt;/col&gt;&lt;tbody valign="top"&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Purpose:&lt;/th&gt;&lt;td class="field-body"&gt;Asynchronous network communication protocol handler&lt;/td&gt;&lt;/tr&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Python Version:&lt;/th&gt;&lt;td class="field-body"&gt;1.5.2 and later&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;The asynchat module builds on &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;asyncore&lt;/span&gt;&lt;/tt&gt; to make it easier to implement protocols based on passing messages back and forth between server and client. The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;async_chat&lt;/span&gt;&lt;/tt&gt; class is an &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;asyncore.dispatcher&lt;/span&gt;&lt;/tt&gt; subclass that receives data and looks for a message terminator. Your subclass only needs to specify what to do when data comes in and how to respond once the terminator is found. Outgoing data is queued for transmission via FIFO objects managed by &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;async_chat&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="section" id="message-terminators"&gt;&lt;h2&gt;Message Terminators&lt;/h2&gt;&lt;p&gt;Incoming messages are broken up based on &lt;em&gt;terminators&lt;/em&gt;, controlled for each instance via &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;set_terminator()&lt;/span&gt;&lt;/tt&gt;. There are three possible configurations:&lt;/p&gt;&lt;ol class="arabic simple"&gt;&lt;li&gt;If a string argument is passed to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;set_terminator()&lt;/span&gt;&lt;/tt&gt;, the message is considered complete when that string appears in the input data.&lt;/li&gt;&lt;li&gt;If a numeric argument is passed, the message is considered complete when that many bytes have been read.&lt;/li&gt;&lt;li&gt;If &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/tt&gt; is passed, message termination is not managed by &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;async_chat&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The EchoServer example below uses both a simple string terminator and a message length terminator, depending on the context of the incoming data. The HTTP request handler example in the standard library documentation offers another example of how to change the terminator based on the context to differentiate between HTTP headers and the HTTP POST request body.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="server-and-handler"&gt;&lt;h2&gt;Server and Handler&lt;/h2&gt;&lt;p&gt;To make it easier to understand how &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;asynchat&lt;/span&gt;&lt;/tt&gt; is different from &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;asyncore&lt;/span&gt;&lt;/tt&gt;, the examples here duplicate the functionality of the EchoServer example from the &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;asyncore&lt;/span&gt;&lt;/tt&gt; discussion. The same basic structure is needed: a server object to accept connections, handler objects to deal with communication with each client, and client objects to initiate the conversation.&lt;/p&gt;&lt;p&gt;The EchoServer needed to work with asynchat is basically the same as the one created for the asyncore-based example, with fewer logging calls because they are less interesting this time around:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncore&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;asynchat_echo_handler&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EchoHandler&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EchoServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dispatcher&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Receives connections and establishes handlers for each client.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dispatcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SOCK_STREAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getsockname&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Called when a client connects to our socket&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;client_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;EchoHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;client_info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# We only want to deal with one client at a time,&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# so close as soon as we set up the handler.&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Normally you would not do this and the server&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# would run forever or until it received instructions&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# to stop.&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handle_close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The EchoHandler is based on &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;asynchat.async_chat&lt;/span&gt;&lt;/tt&gt; instead of the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;asyncore.dispatcher&lt;/span&gt;&lt;/tt&gt; this time around. It operates at a slightly higher level of abstraction, so reading and writing are handled automatically. All we need to do is tell the handler:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;what to do with incoming data (by overriding &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;handle_incoming_data()&lt;/span&gt;&lt;/tt&gt;)&lt;/li&gt;&lt;li&gt;how to recognize the end of an incoming message (via &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;set_terminator()&lt;/span&gt;&lt;/tt&gt;)&lt;/li&gt;&lt;li&gt;what to do when a complete message is received (in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;found_terminator()&lt;/span&gt;&lt;/tt&gt;)&lt;/li&gt;&lt;li&gt;what data to send (using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;push()&lt;/span&gt;&lt;/tt&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In the example application, we have 2 operating modes. We are either waiting for a command of the form &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ECHO&lt;/span&gt; &lt;span class="pre"&gt;length\n&lt;/span&gt;&lt;/tt&gt;, or we are waiting for the data to be echoed. We toggle back and forth between the two modes by setting an instance variable &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;process_data&lt;/span&gt;&lt;/tt&gt; to the method to be invoked when the terminator is found and then changing the terminator as appropriate.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asynchat&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EchoHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asynchat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;async_chat&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Handles echoing messages from a single client.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;received_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;EchoHandler&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getsockname&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;asynchat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;async_chat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Start looking for the ECHO command&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_process_command&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_terminator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;collect_incoming_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Read an incoming message from the client and put it into our outgoing queue.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;collect_incoming_data() -&amp;gt; (&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;received_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;found_terminator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;The end of a command or message has been seen.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;found_terminator()&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_process_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;        &lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;We have the full ECHO command&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;received_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;_process_command() &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;command_verb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command_arg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;expected_data_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command_arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_terminator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected_data_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_process_message&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;received_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_process_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;We have read the entire message to be sent back to the client&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;to_echo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;received_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;_process_message() echoing&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_echo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to_echo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Disconnect after sending the entire response&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# since we only want to do one thing at a time&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close_when_done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Once the complete command is found, we switch to message-processing mode and wait for the complete set of text to be received. When all of the data is available, we push it onto the outgoing channel and set up the handler to be closed once the data is sent.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="client"&gt;&lt;h2&gt;Client&lt;/h2&gt;&lt;p&gt;The client works in much the same way as the handler. As with the &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;asyncore&lt;/span&gt;&lt;/tt&gt; implementation, the message to be sent is an argument to the client&amp;#8217;s constructor. When the socket connection is established, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;handle_connect()&lt;/span&gt;&lt;/tt&gt; is called so we can send the command and message data.&lt;/p&gt;&lt;p&gt;The command is pushed directly, but a special &amp;#8220;producer&amp;#8221; class is used for the message text. The producer is polled for data to send out over the network. When the producer returns an empty string, it is assumed to be empty and writing stops.&lt;/p&gt;&lt;p&gt;The client expects just the message data in response, so it sets an integer terminator and collects data in a list until the entire message has been received.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asynchat&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EchoClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asynchat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;async_chat&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Sends messages to the server and receives responses.&lt;/span&gt;&lt;br /&gt;&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;received_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;EchoClient&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;asynchat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;async_chat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SOCK_STREAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;connecting to &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;handle_connect()&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Send the command&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;ECHO &lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Send the data&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_with_producer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EchoProducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# We expect the data to come back as-is, &lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# so set a length-based terminator&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_terminator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;collect_incoming_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Read an incoming message from the client and put it into our outgoing queue.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;collect_incoming_data() -&amp;gt; (&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;received_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;found_terminator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;found_terminator()&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;received_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;received_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;received_message&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;RECEIVED COPY OF MESSAGE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;ERROR IN TRANSMISSION&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;EXPECTED &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;RECEIVED &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;received_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EchoProducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asynchat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;simple_producer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;EchoProducer&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;more&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asynchat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;simple_producer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;more&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;more() -&amp;gt; (&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="putting-it-all-together"&gt;&lt;h2&gt;Putting It All Together&lt;/h2&gt;&lt;p&gt;The main program for this example sets up the client and server in the same asyncore main loop.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncore&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;asynchat_echo_server&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EchoServer&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;asynchat_echo_client&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EchoClient&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;                    &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%(name)s&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;%(message)s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;                    &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# let the kernel give us a port&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EchoServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="c"&gt;# find out what port we were given&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;message_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;lorem.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EchoClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;message_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Normally you would have them in separate processes, of course, but this makes it easier to show the combined output.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python asynchat_echo_main.py&lt;br /&gt;EchoClient: connecting to ('127.0.0.1', 49919)&lt;br /&gt;EchoClient: handle_connect()&lt;br /&gt;EchoProducer: more() -&amp;gt; (512)&lt;br /&gt;"""Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec&lt;br /&gt;egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a&lt;br /&gt;elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla&lt;br /&gt;facilisi. Sed tristique eros eu libero. Pellentesque vel arcu. Vivamus&lt;br /&gt;purus orci, iaculis ac, suscipit sit amet, pulvinar eu,&lt;br /&gt;lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas&lt;br /&gt;dui. Pellentesque habitant morbi tristique senectus et netus et&lt;br /&gt;malesuada fames ac turpis egestas. Aliquam viverra f"""&lt;br /&gt;EchoProducer: more() -&amp;gt; (512)&lt;br /&gt;"""ringilla&lt;br /&gt;leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed&lt;br /&gt;mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut&lt;br /&gt;eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet&lt;br /&gt;justo.&lt;br /&gt;Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec&lt;br /&gt;egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a&lt;br /&gt;elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla&lt;br /&gt;facilisi. Sed tristique eros eu libero. Pellentesque vel arcu. Vivamus&lt;br /&gt;purus orci, iac"""&lt;br /&gt;EchoHandler('127.0.0.1', 49919): collect_incoming_data() -&amp;gt; (9)&lt;br /&gt;"""ECHO 1474"""&lt;br /&gt;EchoHandler('127.0.0.1', 49919): found_terminator()&lt;br /&gt;EchoHandler('127.0.0.1', 49919): _process_command() "ECHO 1474"&lt;br /&gt;EchoHandler('127.0.0.1', 49919): collect_incoming_data() -&amp;gt; (1024)&lt;br /&gt;"""Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec&lt;br /&gt;egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a&lt;br /&gt;elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla&lt;br /&gt;facilisi. Sed tristique eros eu libero. Pellentesque vel arcu. Vivamus&lt;br /&gt;purus orci, iaculis ac, suscipit sit amet, pulvinar eu,&lt;br /&gt;lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas&lt;br /&gt;dui. Pellentesque habitant morbi tristique senectus et netus et&lt;br /&gt;malesuada fames ac turpis egestas. Aliquam viverra fringilla&lt;br /&gt;leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed&lt;br /&gt;mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut&lt;br /&gt;eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet&lt;br /&gt;justo.&lt;br /&gt;Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec&lt;br /&gt;egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a&lt;br /&gt;elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla&lt;br /&gt;facilisi. Sed tristique eros eu libero. Pellentesque vel arcu. Vivamus&lt;br /&gt;purus orci, iac"""&lt;br /&gt;EchoProducer: more() -&amp;gt; (450)&lt;br /&gt;"""ulis ac, suscipit sit amet, pulvinar eu,&lt;br /&gt;lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas&lt;br /&gt;dui. Pellentesque habitant morbi tristique senectus et netus et&lt;br /&gt;malesuada fames ac turpis egestas. Aliquam viverra fringilla&lt;br /&gt;leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed&lt;br /&gt;mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut&lt;br /&gt;eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet&lt;br /&gt;justo.&lt;br /&gt;"""&lt;br /&gt;EchoHandler('127.0.0.1', 49919): collect_incoming_data() -&amp;gt; (450)&lt;br /&gt;"""ulis ac, suscipit sit amet, pulvinar eu,&lt;br /&gt;lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas&lt;br /&gt;dui. Pellentesque habitant morbi tristique senectus et netus et&lt;br /&gt;malesuada fames ac turpis egestas. Aliquam viverra fringilla&lt;br /&gt;leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed&lt;br /&gt;mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut&lt;br /&gt;eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet&lt;br /&gt;justo.&lt;br /&gt;"""&lt;br /&gt;EchoHandler('127.0.0.1', 49919): found_terminator()&lt;br /&gt;EchoHandler('127.0.0.1', 49919): _process_message() echoing&lt;br /&gt;"""Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec&lt;br /&gt;egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a&lt;br /&gt;elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla&lt;br /&gt;facilisi. Sed tristique eros eu libero. Pellentesque vel arcu. Vivamus&lt;br /&gt;purus orci, iaculis ac, suscipit sit amet, pulvinar eu,&lt;br /&gt;lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas&lt;br /&gt;dui. Pellentesque habitant morbi tristique senectus et netus et&lt;br /&gt;malesuada fames ac turpis egestas. Aliquam viverra fringilla&lt;br /&gt;leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed&lt;br /&gt;mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut&lt;br /&gt;eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet&lt;br /&gt;justo.&lt;br /&gt;Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec&lt;br /&gt;egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a&lt;br /&gt;elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla&lt;br /&gt;facilisi. Sed tristique eros eu libero. Pellentesque vel arcu. Vivamus&lt;br /&gt;purus orci, iaculis ac, suscipit sit amet, pulvinar eu,&lt;br /&gt;lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas&lt;br /&gt;dui. Pellentesque habitant morbi tristique senectus et netus et&lt;br /&gt;malesuada fames ac turpis egestas. Aliquam viverra fringilla&lt;br /&gt;leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed&lt;br /&gt;mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut&lt;br /&gt;eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet&lt;br /&gt;justo.&lt;br /&gt;"""&lt;br /&gt;EchoProducer: more() -&amp;gt; (0)&lt;br /&gt;""""""&lt;br /&gt;EchoClient: collect_incoming_data() -&amp;gt; (512)&lt;br /&gt;"""Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec&lt;br /&gt;egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a&lt;br /&gt;elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla&lt;br /&gt;facilisi. Sed tristique eros eu libero. Pellentesque vel arcu. Vivamus&lt;br /&gt;purus orci, iaculis ac, suscipit sit amet, pulvinar eu,&lt;br /&gt;lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas&lt;br /&gt;dui. Pellentesque habitant morbi tristique senectus et netus et&lt;br /&gt;malesuada fames ac turpis egestas. Aliquam viverra f"""&lt;br /&gt;EchoClient: collect_incoming_data() -&amp;gt; (512)&lt;br /&gt;"""ringilla&lt;br /&gt;leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed&lt;br /&gt;mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut&lt;br /&gt;eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet&lt;br /&gt;justo.&lt;br /&gt;Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec&lt;br /&gt;egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a&lt;br /&gt;elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla&lt;br /&gt;facilisi. Sed tristique eros eu libero. Pellentesque vel arcu. Vivamus&lt;br /&gt;purus orci, iac"""&lt;br /&gt;EchoClient: collect_incoming_data() -&amp;gt; (450)&lt;br /&gt;"""ulis ac, suscipit sit amet, pulvinar eu,&lt;br /&gt;lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas&lt;br /&gt;dui. Pellentesque habitant morbi tristique senectus et netus et&lt;br /&gt;malesuada fames ac turpis egestas. Aliquam viverra fringilla&lt;br /&gt;leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed&lt;br /&gt;mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut&lt;br /&gt;eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet&lt;br /&gt;justo.&lt;br /&gt;"""&lt;br /&gt;EchoClient: found_terminator()&lt;br /&gt;EchoClient: RECEIVED COPY OF MESSAGE&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/asynchat.html"&gt;asynchat&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for this module.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;asyncore&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;The asyncore module implements an lower-level asynchronous I/O event loop.&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-8057260674891283712?l=blog.doughellmann.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.doughellmann.com/feeds/8057260674891283712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=8057260674891283712' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/8057260674891283712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5440028356946346379/posts/default/8057260674891283712'/><link rel='alternate' type='text/html' href='http://blog.doughellmann.com/2009/03/pymotw-asynchat.html' title='PyMOTW: asynchat'/><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='00116818175230541568'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry></feed>