<divid="unreleased-message"> You are reading an old version of the documentation (v2.2.4). For the latest version see <ahref="/stable/">https://matplotlib.org/stable/</a></div>
<h3><ahref="../contents.html">Table of Contents</a></h3>
<ul>
<li><aclass="reference internal" href="#">Developer's tips for writing code for Python 2 and 3</a><ul>
<li><aclass="reference internal" href="#welcome-to-the-future">Welcome to the <codeclass="docutils literal notranslate"><spanclass="pre">__future__</span></code></a></li>
<li><aclass="reference internal" href="#finding-places-to-use-six">Finding places to use six</a></li>
<spanid="portable-code"></span><h1>Developer's tips for writing code for Python 2 and 3<aclass="headerlink" href="#developer-s-tips-for-writing-code-for-python-2-and-3" title="Permalink to this headline">¶</a></h1>
<p>As of matplotlib 1.4, the <aclass="reference external" href="http://pythonhosted.org/six/">six</a>
library is used to support Python 2 and 3 from a single code base.
The <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">2to3</span></code> tool is no longer used.</p>
<p>This document describes some of the issues with that approach and some
recommended solutions. It is not a complete guide to Python 2 and 3
compatibility.</p>
<divclass="section" id="welcome-to-the-future">
<h2>Welcome to the <codeclass="docutils literal notranslate"><spanclass="pre">__future__</span></code><aclass="headerlink" href="#welcome-to-the-future" title="Permalink to this headline">¶</a></h2>
<p>The top of every <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">py</span></code> file should include the following:</p>
<p>This will make the Python 2 interpreter behave as close to Python 3 as
possible.</p>
<p>All matplotlib files should also import <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">six</span></code>, whether they are using
it or not, just to make moving code between modules easier, as <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">six</span></code>
<h2>Finding places to use six<aclass="headerlink" href="#finding-places-to-use-six" title="Permalink to this headline">¶</a></h2>
<p>The only way to make sure code works on both Python 2 and 3 is to make sure it
is covered by unit tests.</p>
<p>However, the <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">2to3</span></code> commandline tool can also be used to locate places
that require special handling with <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">six</span></code>.</p>
<p>(The <aclass="reference external" href="https://pypi.python.org/pypi/modernize">modernize</a> tool may
also be handy, though I've never used it personally).</p>
<p>The <aclass="reference external" href="http://pythonhosted.org/six/">six</a> documentation serves as a
good reference for the sorts of things that need to be updated.</p>
</div>
<divclass="section" id="the-dreaded-u-escapes">
<h2>The dreaded <codeclass="docutils literal notranslate"><spanclass="pre">\u</span></code> escapes<aclass="headerlink" href="#the-dreaded-u-escapes" title="Permalink to this headline">¶</a></h2>
<p>When <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">__future__</span><spanclass="pre">import</span><spanclass="pre">unicode_literals</span></code> is used, all string
literals (not preceded with a <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">b</span></code>) will become unicode literals.</p>
<p>Normally, one would use "raw" string literals to encode strings that
contain a lot of slashes that we don't want Python to interpret as
special characters. A common example in matplotlib is when it deals
with TeX and has to represent things like <codeclass="docutils literal notranslate"><spanclass="pre">r"\usepackage{foo}"</span></code>.
Unfortunately, on Python 2there is no way to represent <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">u</span></code> in a raw
unicode string literal, since it will always be interpreted as the
start of a unicode character escape, such as <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">u20af</span></code>. The only
solution is to use a regular (non-raw) string literal and repeat all
slashes, e.g. <codeclass="docutils literal notranslate"><spanclass="pre">"\\usepackage{foo}"</span></code>.</p>
<p>The following shows the problem on Python 2:</p>
<h2>Iteration<aclass="headerlink" href="#iteration" title="Permalink to this headline">¶</a></h2>
<p>The behavior of the methods for iterating over the items, values and
keys of a dictionary has changed in Python 3. Additionally, other
built-in functions such as <aclass="reference external" href="https://docs.python.org/3/library/functions.html#zip" title="(in Python v3.7)"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">zip</span></code></a>, <aclass="reference external" href="https://docs.python.org/3/library/stdtypes.html#range" title="(in Python v3.7)"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">range</span></code></a> and <aclass="reference external" href="https://docs.python.org/3/library/functions.html#map" title="(in Python v3.7)"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">map</span></code></a> have changed to
return iterators rather than temporary lists.</p>
<p>In many cases, the performance implications of iterating vs. creating
a temporary list won't matter, so it's tempting to use the form that
is simplest to read. However, that results in code that behaves
differently on Python 2 and 3, leading to subtle bugs that may not be
detected by the regression tests. Therefore, unless the loop in
question is provably simple and doesn't call into other code, the
<codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">six</span></code> versions that ensure the same behavior on both Python 2 and 3
should be used. The following table shows the mapping of equivalent
semantics between Python 2, 3 and six for <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">dict.items()</span></code>:</p>