title: Python asyncio, futures and yield from
body: <p>Consider the following program (running on CPython 3.4.0b1):</p>
  
  <pre><code>import math
  import asyncio
  from asyncio import coroutine
  
  @coroutine
  def fast_sqrt(x):
     future = asyncio.Future()
     if x &gt;= 0:
        future.set_result(math.sqrt(x))
     else:
        future.set_exception(Exception("negative number"))
     return future
  
  
  def slow_sqrt(x):
     yield from asyncio.sleep(1)
     future = asyncio.Future()
     if x &gt;= 0:
        future.set_result(math.sqrt(x))
     else:
        future.set_exception(Exception("negative number"))
     return future
  
  
  @coroutine
  def run_test():
     for x in [2, -2]:
        for f in [fast_sqrt, slow_sqrt]:
           try:
              future = yield from f(x)
              print("\n{} {}".format(future, type(future)))
              res = future.result()
              print("{} result: {}".format(f, res))
           except Exception as e:
              print("{} exception: {}".format(f, e))
  
  
  loop = asyncio.get_event_loop()
  loop.run_until_complete(run_test())
  </code></pre>
  
  <p>I have 2 (related) questions:</p>
  
  <ol>
  <li><p>Even with the decorator on <code>fast_sqrt</code>, Python seems to optimize away the Future created in <code>fast_sqrt</code> altogether, and a plain <code>float</code> is returned. Which then blows up in <code>run_test()</code> in the <code>yield from</code></p></li>
  <li><p>Why do I need to evaluate <code>future.result()</code> in <code>run_test</code> to retrieve the value of fire the exception? The <a href="http://docs.python.org/3.4/library/asyncio-task.html">docs</a> say that <code>yield from &lt;future&gt;</code> "suspends the coroutine until the future is done, then returns the future’s result, or raises an exception". Why do I manually need to retieve the future's result?</p></li>
  </ol>
  
  <p>Here is what I get:</p>
  
  <pre><code>oberstet@COREI7 ~/scm/tavendo/infrequent/scratchbox/python/asyncio (master)
  $ python3 -V
  Python 3.4.0b1
  oberstet@COREI7 ~/scm/tavendo/infrequent/scratchbox/python/asyncio (master)
  $ python3 test3.py
  
  1.4142135623730951 &lt;class 'float'&gt;
  &lt;function fast_sqrt at 0x00B889C0&gt; exception: 'float' object has no attribute 'result'
  
  Future&lt;result=1.4142135623730951&gt; &lt;class 'asyncio.futures.Future'&gt;
  &lt;function slow_sqrt at 0x02AC8810&gt; result: 1.4142135623730951
  &lt;function fast_sqrt at 0x00B889C0&gt; exception: negative number
  
  Future&lt;exception=Exception('negative number',)&gt; &lt;class 'asyncio.futures.Future'&gt;
  &lt;function slow_sqrt at 0x02AC8810&gt; exception: negative number
  oberstet@COREI7 ~/scm/tavendo/infrequent/scratchbox/python/asyncio (master)
  </code></pre>
  
  <p>Ok, I found the "issue". The <code>yield from asyncio.sleep</code> in <code>slow_sqrt</code> will make it a coroutine automatically. The waiting needs to be done differently:</p>
  
  <pre><code>def slow_sqrt(x):
     loop = asyncio.get_event_loop()
     future = asyncio.Future()
     def doit():
        if x &gt;= 0:
           future.set_result(math.sqrt(x))
        else:
           future.set_exception(Exception("negative number"))
     loop.call_later(1, doit)
     return future
  </code></pre>
  
  <p>All 4 variants are <a href="https://github.com/oberstet/scratchbox/blob/master/python/asyncio/test3.py">here</a>.</p>