am.torrinha
am.torrinha

Reputation: 59

How do I call an async function with method run_in_executor in Python/Tornado?

I have a python file where I have a tornado request handler class with the following relevant code:

executor = concurrent.futures.ThreadPoolExecutor(max_workers = 20)
from tornado.platform.asyncio import AnyThreadEventLoopPolicy
asyncio.set_event_loop_policy(AnyThreadEventLoopPolicy())

class MainHandler(tornado.web.RequestHandler):
   async def connect(self):
      # some code
      loop = asyncio.get_event_loop()
      await loop.run_in_executor(executor, self.connect_function)

   async def connect_function(self):
      #some code with an await operation somewhere here

So my main goal is to be able to use the request handler with threads. The way I found I could do this is with the method run_in_executor. The problem here is that in the connect method I want to await the end of connect_function which also is async, this usually raises an error: RuntimeWarning: coroutine 'MainHandler.connect_function' was never awaited . My questions are if is this the only way I can make threads work in this tornado request handler, and if so, if there's a way I can wait the execution of an async function with the method run_in_executor.

Upvotes: 0

Views: 9236

Answers (3)

user3761555
user3761555

Reputation: 1245

Okay, in simple English.

Take fetch_reference_fx (It's an async function) as example,

Instead of:

fetches = [
                    one_loop.run_in_executor(None, fetch_reference_fx, price_sources, vwap_num_levels, self.app_context.logger),
                ]
results = await asyncio.gather(*fetches)

Do this instead:

fetches = [
                    fetch_reference_fx(price_sources, vwap_num_levels, self.app_context.logger)
                ]
results = await asyncio.gather(*fetches)

Hope this helps.

Upvotes: 0

Ben Darnell
Ben Darnell

Reputation: 22134

You can't run async functions in a ThreadPoolExecutor (unless you also run another event loop there, which is not usually what you want). You could schedule a callback on the main event loop and then wait for it on the thread, but that's complex. As a general rule, when you're using an async framework like Tornado, you want to stay on the event loop thread as much as possible, and only send things out to a ThreadPoolExecutor when necessary (and then let those functions return to the main thread instead of trying to call back to async code from the thread).

Upvotes: 5

user3732793
user3732793

Reputation: 1939

asynch handling has changed with version 6 I think.

So some examples / howtos might be misleading. You probably want to look the the tornado documentation page for the latest examples. Like here scroll down for the asynch code examples

Upvotes: -1

Related Questions