有一个棘手的post handler,有时会花很多时间(取决于输入值),有时不会。
我想要的是每当1秒过后就回写,动态分配响应。
def post():
def callback():
self.write('too-late')
self.finish()
timeout_obj = IOLoop.current().add_timeout(
dt.timedelta(seconds=1),
callback,
)
# some asynchronous operations
if not self.request.connection.stream.closed():
self.write('here is your response')
self.finish()
IOLoop.current().remove_timeout(timeout_obj)
事实证明,我不能从内部的 callback
.
即使是引发异常,也会被内部上下文所抑制,不会通过 post
的方法。
还有其他方法可以达到目的吗?
谢谢你了。
更新2020-05-15我发现类似的 疑问
谢谢 @ionut-ticus, 使用 with_timeout()
是更方便。
经过一番尝试,我想我真的很接近我要找的东西了。
def wait(fn):
@gen.coroutine
@wraps(fn)
def wrap(*args):
try:
result = yield gen.with_timeout(
dt.timedelta(seconds=20),
IOLoop.current().run_in_executor(None, fn, *args),
)
raise gen.Return(result)
except gen.TimeoutError:
logging.error('### TOO LONG')
raise gen.Return('Next time, bro')
return wrap
@wait
def blocking_func(item):
time.sleep(30)
# this is not a Subprocess.
# It is a file IO and DB
return 'we are done here'
还不确定,应该 wait()
被包裹着的装饰者迂回曲折?
有些时候,在连环夺宝的 blocking_func()
可以有另一个 线程池执行器. 我有个担心,如果不把 "我的 "变成全局性的,然后传递给 "我的",这能行吗?龙卷风's run_in_executor()
?
龙卷风: v5.1.1
以下是一个使用实例 tornado.gen.with_timeout
. 请记住,任务需要是async,否则IOLoop会被阻塞,无法处理超时。
@gen.coroutine
def async_task():
# some async code
@gen.coroutine
def get(self):
delta = datetime.timedelta(seconds=1)
try:
task = self.async_task()
result = yield gen.with_timeout(delta, task)
self.write("success")
except gen.TimeoutError:
self.write("timeout")
我建议使用 https:/github.comaio-libsasync-timeout。:
import asyncio
import async_timeout
def post():
try:
async with async_timeout.timeout(1):
# some asynchronous operations
if not self.request.connection.stream.closed():
self.write('here is your response')
self.finish()
IOLoop.current().remove_timeout(timeout_obj)
except asyncio.TimeoutError:
self.write('too-late')
self.finish()