Как лучше всего установить условие тайм-аута для функций, украшенных @run_on_executor в Tornado?

#python-3.x #tornado

Вопрос:

Каков был бы наилучший подход для установки условия тайм-аута для задачи/функции, которая была отправлена в ThreadPoolExecutor с помощью декоратора @run_on_executor tornado.concurrent? Пример обработчика торнадо ниже:

 import json
import time
import tornado.web
from concurrent.futures import ThreadPoolExecutor
from tornado.concurrent import run_on_executor


class MyHandler(tornado.web.RequestHandler):

    def initialize(self) -> None:
        self.executor = ThreadPoolExecutor(1)

    @run_on_executor
    def blocking_function(self) -> None:
        """ Run Blocking Function on ThreadPoolExecutor. """
        seconds = 10
        time.sleep(seconds)
        response = json.dumps({"message": f"Slept for {seconds} seconds."})
        return response

    async def get(self) -> None:
        response = await self.blocking_function()
        self.write(response)
 

Существует ли что-то подобное tornado.gen.with_timeout найденному здесь для @run_on_executor?

Спасибо, что уделили мне время.

Ответ №1:

Поскольку run_on_executor возвращает Future объект, вы можете использовать его с gen.with_timetout :

 from datetime import timedelta

async def get(self):
    response = await gen.with_timeout(
                   timedelta(seconds=5),
                   self.blocking_function()
               )

    ...
 

Не забудьте обработать исключение тайм-аута.

Комментарии:

1. Эй, @xyres, спасибо за ваш ответ, но эти опции, похоже, обеспечивают поведение «вызов через 5 секунд», когда на самом деле я прошу «отменить через 5 секунд». Поэтому в моем примере я бы хотел async def get(self) , чтобы вызов вызывал исключение, если соблюдено значение тайм-аута (например, 5 секунд). В данном случае так и должно быть, потому blocking_function() что для завершения вызова должно потребоваться более или равно 10 секунд. Я могу отредактировать исходный вопрос, если вы считаете, что это было непонятно, еще раз спасибо.

2. Извините, я раньше не понял вопроса. Теперь я обновил свой ответ. Посмотрим, поможет ли это.

3. Именно то, что было нужно, спасибо!