简体   繁体   English

如何在 Python/Tornado 中使用 run_in_executor 方法调用异步函数?

[英]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:我有一个 python 文件,其中有一个带有以下相关代码的龙卷风请求处理程序类:

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 .我发现我可以做到这一点的方法是使用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 .这里的问题是,在connect方法中,我想等待也是异步的connect_function结束,这通常会引发错误: 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 .我的问题是,如果这是我可以让线程在这个龙卷风请求处理程序中工作的唯一方法,如果是这样,如果有一种方法我可以使用run_in_executor方法等待异步函数的执行。

You can't run async functions in a ThreadPoolExecutor (unless you also run another event loop there, which is not usually what you want).您不能在 ThreadPoolExecutor 中运行异步函数(除非您还在那里运行另一个事件循环,这通常不是您想要的)。 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).作为一般规则,当您使用像 Tornado 这样的异步框架时,您希望尽可能地留在事件循环线程上,并且仅在必要时将事情发送到 ThreadPoolExecutor(然后让这些函数return到主线程而不是尝试从线程回调异步代码)。

asynch handling has changed with version 6 I think.我认为异步处理随着版本 6 的变化而改变。

So some examples / howtos might be misleading.所以一些例子/howtos可能会产生误导。 You probably want to look the the tornado documentation page for the latest examples.您可能想查看 tornado 文档页面以获取最新示例。 Like here scroll down for the asynch code examples这里向下滚动异步代码示例

Okay, in simple English.好的,简单的英语。

Take fetch_reference_fx (It's an async function) as example,fetch_reference_fx (它是一个异步函数)为例,

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.希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM