Python tornado gen.coroutine blocks request
<p>I am newbie on tornado and python. A couple days ago i started to write a non-blocking rest api, but i couldn't accomplish the mission yet. When i send two request to this endpoint "localhost:8080/async" at the same time, the second request takes response after 20 seconds! That explains i am doing something wrong.</p>

<pre><code>MAX_WORKERS = 4
class ASYNCHandler(tornado.web.RequestHandler):
    executor = ThreadPoolExecutor(max_workers=MAX_WORKERS)
    counter = 0

    def pow_task(self, x, y):
        time.sleep(10)
        return pow(x,y)

    async def background_task(self):
        future = ASYNCHandler.executor.submit(self.pow_task, 2, 3)
        return future

    @gen.coroutine
    def get(self, *args, **kwargs):
        future = yield from self.background_task()
        response=  dumps({"result":future.result()}, default=json_util.default)
        print(response)


application = tornado.web.Application([
        ('/async', ASYNCHandler),
        ('/sync', SYNCHandler),
    ], db=db, debug=True)  
application.listen(8888)
tornado.ioloop.IOLoop.current().start()
</code></pre>

<p>That's strange that returning the <code>ThreadPoolExecutor</code> future, essentially blocks tornado's event loop. If anyone from the tornado team reads this and knows why that is, can they please give an explaination? I had planned to do some stuff with threads in tornado but after dealing with this question, I see that it's not going to be as simple as I originally anticipated. In any case, here is the code which does what you expect (I've trimmed your original example down a bit so that anyone can run it quickly):</p>

<pre><code>from concurrent.futures import ThreadPoolExecutor
from json import dumps
import time
from tornado.platform.asyncio import to_tornado_future
from tornado.ioloop import IOLoop
from tornado import gen, web

MAX_WORKERS = 4

class ASYNCHandler(web.RequestHandler):
    executor = ThreadPoolExecutor(max_workers=MAX_WORKERS)
    counter = 0

    def pow_task(self, x, y):
        time.sleep(5)
        return pow(x,y)

    async def background_task(self):
        future = self.executor.submit(self.pow_task, 2, 3)
        result = await to_tornado_future(future)    # convert to tornado future
        return result

    @gen.coroutine
    def get(self, *args, **kwargs):
        result = yield from self.background_task()
        response = dumps({"result": result})
        self.write(response)


application = web.Application([
        ('/async', ASYNCHandler),
    ], debug=True)
application.listen(8888)
IOLoop.current().start()
</code></pre>

<p>The main differences are in the <code>background_tasks()</code> method. I convert the <code>asyncio</code> future to a <code>tornado</code> future, wait for the result, then return the result. The code you provided in the question, blocked for some reason when yielding from  <code>background_task()</code> and you were unable to <code>await</code> the result because the future wasn't a tornado future.</p>

<p>On a slightly different note, this simple example can easily be implemented using a single thread/async designs and chances are your code can also be done without threads. Threads are easy to implement but equally easy to get wrong and can lead to very sticky situations. When attempting to write threaded code please remember <a href="http://bholley.net/images/posts/thistall.jpg" rel="nofollow">this photo</a> :)</p>

python tornado python-3.5