Skip to content
Snippets Groups Projects
Commit e025a5c8 authored by Armin Rigo's avatar Armin Rigo
Browse files

Rewrite a bit this section to focus on the commonly-encountered issue

of non-exhausted generators.  Found out that they have a close() method.
parent 999af31a
No related branches found
No related tags found
No related merge requests found
......@@ -106,13 +106,12 @@
<li>Pillow (the PIL fork)</li>
<li><a class="reference external" href="https://github.com/amauryfa/lxml/tree/cffi/">lxml</a></li>
</ul>
<p>Known differences that are not going to be fixed:</p>
<ul>
<li><p class="first">PyPy does not support refcounting semantics. The following code
won't fill the file immediately, but only after a certain period
of time, when the GC does a collection:</p>
<p>The main difference that is not going to be fixed is that PyPy does
not support refcounting semantics. The following code won't fill the
file immediately, but only after a certain period of time, when the GC
does a collection:</p>
<div class="syntax python"><pre><span class="nb">open</span><span class="p">(</span><span class="s">&quot;filename&quot;</span><span class="p">,</span> <span class="s">&quot;w&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&quot;stuff&quot;</span><span class="p">)</span><br/></pre></div>
<p>The proper fix is</p>
<div class="syntax python"><pre><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">&quot;filename&quot;</span><span class="p">,</span> <span class="s">&quot;w&quot;</span><span class="p">)</span><br/><span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&quot;stuff&quot;</span><span class="p">)</span><br/><span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span><br/></pre></div>
<p>or using the <tt class="docutils literal">with</tt> keyword</p>
<div class="syntax python"><pre><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">&quot;filename&quot;</span><span class="p">,</span> <span class="s">&quot;w&quot;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span><br/> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&quot;stuff&quot;</span><span class="p">)</span><br/></pre></div>
......@@ -114,26 +113,17 @@
<div class="syntax python"><pre><span class="nb">open</span><span class="p">(</span><span class="s">&quot;filename&quot;</span><span class="p">,</span> <span class="s">&quot;w&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&quot;stuff&quot;</span><span class="p">)</span><br/></pre></div>
<p>The proper fix is</p>
<div class="syntax python"><pre><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">&quot;filename&quot;</span><span class="p">,</span> <span class="s">&quot;w&quot;</span><span class="p">)</span><br/><span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&quot;stuff&quot;</span><span class="p">)</span><br/><span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span><br/></pre></div>
<p>or using the <tt class="docutils literal">with</tt> keyword</p>
<div class="syntax python"><pre><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">&quot;filename&quot;</span><span class="p">,</span> <span class="s">&quot;w&quot;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span><br/> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&quot;stuff&quot;</span><span class="p">)</span><br/></pre></div>
<p>See <a class="reference external" href="http://pypy.readthedocs.org/en/latest/cpython_differences.html#differences-related-to-garbage-collection-strategies">more details here</a>.</p>
</li>
<li><p class="first">For the same reason, some functions and attributes of the <tt class="docutils literal">gc</tt> module
behave in a slightly different way: for example, <tt class="docutils literal">gc.enable</tt> and
<tt class="docutils literal">gc.disable</tt> are supported, but instead of enabling and disabling the GC,
they just enable and disable the execution of finalizers. Also,
<tt class="docutils literal">gc.garbage</tt> always returns an empty list.</p>
</li>
<li><p class="first">You can't add a <tt class="docutils literal">__del__</tt> method to an existing class; it
must be present in the class since the beginning, or else it
will not be automatically called when instances are freed.</p>
</li>
<li><p class="first">You can't store non-string keys in type objects. Example</p>
<div class="syntax python"><pre><span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span><br/> <span class="nb">locals</span><span class="p">()[</span><span class="mi">42</span><span class="p">]</span> <span class="o">=</span> <span class="mi">3</span><br/></pre></div>
<p>won't work.</p>
</li>
</ul>
<p>A more complete list is available at <a class="reference external" href="http://pypy.readthedocs.org/en/latest/cpython_differences.html">our dev site</a>.</p>
<p>Similarly, remember that you must <tt class="docutils literal">close()</tt> a non-exhausted
generator in order to have its pending <tt class="docutils literal">finally</tt> or <tt class="docutils literal">with</tt>
clauses executed immediately:</p>
<div class="syntax python"><pre><span class="k">def</span> <span class="nf">mygen</span><span class="p">():</span><br/> <span class="k">with</span> <span class="n">foo</span><span class="p">:</span><br/> <span class="k">yield</span> <span class="mi">42</span><br/><br/><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">mygen</span><span class="p">():</span><br/> <span class="k">if</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">42</span><span class="p">:</span><br/> <span class="k">break</span> <span class="c"># foo.__exit__ is not run immediately!</span><br/><br/><span class="c"># fixed version:</span><br/><span class="n">gen</span> <span class="o">=</span> <span class="n">mygen</span><span class="p">()</span><br/><span class="k">try</span><span class="p">:</span><br/> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">gen</span><span class="p">:</span><br/> <span class="k">if</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">42</span><span class="p">:</span><br/> <span class="k">break</span><br/><span class="k">finally</span><span class="p">:</span><br/> <span class="n">gen</span><span class="o">.</span><span class="n">close</span><span class="p">()</span><br/></pre></div>
<p>More generally, <tt class="docutils literal">__del__()</tt> methods are not executed as predictively
as on CPython: they run &ldquo;some time later&rdquo; in PyPy (or not at all if
the program finishes running in the meantime). See <a class="reference external" href="http://pypy.readthedocs.org/en/latest/cpython_differences.html#differences-related-to-garbage-collection-strategies">more details
here</a>.</p>
<p>A more complete list of known differences is available at <a class="reference external" href="http://pypy.readthedocs.org/en/latest/cpython_differences.html">our dev site</a>.</p>
</div>
<div id="sidebar">
</div>
......
......@@ -58,5 +58,8 @@
* `lxml`_
Known differences that are not going to be fixed:
The main difference that is not going to be fixed is that PyPy does
not support refcounting semantics. The following code won't fill the
file immediately, but only after a certain period of time, when the GC
does a collection:
......@@ -62,9 +65,5 @@
* PyPy does not support refcounting semantics. The following code
won't fill the file immediately, but only after a certain period
of time, when the GC does a collection:
.. syntax:: python
.. syntax:: python
open("filename", "w").write("stuff")
......@@ -68,5 +67,5 @@
open("filename", "w").write("stuff")
The proper fix is
The proper fix is
......@@ -72,7 +71,7 @@
.. syntax:: python
.. syntax:: python
f = open("filename", "w")
f.write("stuff")
f.close()
......@@ -74,7 +73,7 @@
f = open("filename", "w")
f.write("stuff")
f.close()
or using the ``with`` keyword
or using the ``with`` keyword
......@@ -80,6 +79,6 @@
.. syntax:: python
.. syntax:: python
with open("filename", "w") as f:
f.write("stuff")
......@@ -82,6 +81,10 @@
with open("filename", "w") as f:
f.write("stuff")
See `more details here`_.
Similarly, remember that you must ``close()`` a non-exhausted
generator in order to have its pending ``finally`` or ``with``
clauses executed immediately:
.. syntax:: python
......@@ -87,7 +90,9 @@
* For the same reason, some functions and attributes of the ``gc`` module
behave in a slightly different way: for example, ``gc.enable`` and
``gc.disable`` are supported, but instead of enabling and disabling the GC,
they just enable and disable the execution of finalizers. Also,
``gc.garbage`` always returns an empty list.
def mygen():
with foo:
yield 42
for x in mygen():
if x == 42:
break # foo.__exit__ is not run immediately!
......@@ -93,7 +98,10 @@
* You can't add a ``__del__`` method to an existing class; it
must be present in the class since the beginning, or else it
will not be automatically called when instances are freed.
* You can't store non-string keys in type objects. Example
# fixed version:
gen = mygen()
try:
for x in gen:
if x == 42:
break
finally:
gen.close()
......@@ -99,3 +107,6 @@
.. syntax:: python
More generally, ``__del__()`` methods are not executed as predictively
as on CPython: they run "some time later" in PyPy (or not at all if
the program finishes running in the meantime). See `more details
here`_.
......@@ -101,10 +112,5 @@
class A(object):
locals()[42] = 3
won't work.
A more complete list is available at `our dev site`_.
A more complete list of known differences is available at `our dev site`_.
.. _`CPython C API`: http://docs.python.org/c-api/
.. _`CFFI`: http://cffi.readthedocs.org/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment