私はに探しています:ラップ操作(s)は、時間の所定の長さを超えた場合ContextDecorator内でTornadoタイムアウト例外を発生させるにはどうすればよいですか?
- は
- が出先制含めるログ/他のタイミングの目的のために、カスタムタイマーラッパーを作る
from contextlib import ContextDecorator
import datetime
from tornado import gen, ioloop
from tornado.concurrent import Future
class timing_logger(ContextDecorator):
def __init__(self, allowed_ms):
self.allowed_ms = allowed_ms
self.f = Future()
# this exception is not bubbled up by Tornado but fires
gen.with_timeout(datetime.timedelta(seconds=1+allowed_ms/1000), self.f)
def __enter__(self):
self.start_time = datetime.datetime.now()
return self
def __exit__(self, exc_type, exc_val, traceback):
self.f.set_result(True)
elapsed_time_ms = (datetime.datetime.now() - self.start_time).total_seconds() * 1000
if exc_type == gen.TimeoutError:
raise TimeoutError('ruh oh, this is reeeally bad')
if elapsed_time_ms > self.allowed_ms:
raise TimeoutError('took {actual} ms, but was only allowed {allowed}.'.format(
actual=elapsed_time_ms, allowed=self.allowed_ms))
else:
print('worked. nothing to see here...')
return False
@gen.coroutine
def main():
with timing_logger(1000):
# real application may be a variety of coroutines
# and regular function calls, some of which may hang
# for a long time
for i in range(25):
yield gen.sleep(0.1)
if __name__ == "__main__":
ioloop.IOLoop.current().run_sync(
lambda: main())
私がここに持っている問題は、私はをもたらすわけではないので、ということである:これは私がこれまで持っているものです0将来、私が見スタックに:
$python test.py
ERROR:tornado.application:Future <tornado.concurrent.Future object at 0x10c7cb668> exception was never retrieved: tornado.gen.TimeoutError: Timeout
Traceback (most recent call last):
File "test.py", line 48, in <module>
lambda: main())
<snip>
yielded = self.gen.send(value)
File "test.py", line 43, in main
yield gen.sleep(0.1)
File "test.py", line 28, in __exit__
actual=elapsed_time_ms, allowed=self.allowed_ms))
TimeoutError: took 2606.2940000000003 ms, but was only allowed 1000.
竜巻のタイムアウトがが(もっと良い言葉がないために)「バブリング」されていません。
__exit__
は例外をキャプチャして、適切に処理し、別の例外タイプとして再発生させることができます。
私は私がする必要があるかどうかわからないです:
- はすべて
- でContextDecoratorを使用しない方法/どこ私は竜巻コール
- を持っていると別の何かを行います????
@gen.coroutine def main(): @gen.coroutine def f(): with timing_logger(1000): # real application may be a variety of coroutines # and regular function calls, some of which may hang # for a long time for i in range(25): yield gen.sleep(0.1) future = f() yield gen.with_timeout(datetime.timedelta(seconds=1), future)
しかし、私は:私はこの例では、私はコルーチンにすべての呼び出し元のコードをラップすることができますし、このように、タイミングロガーラップの周り
main
機能にタイムアウトを追加することを知っている
上記を私のContextDecoratorに含めると、timing_logger
を使用したいすべてのものをコピーしなければならないので、エラーが発生しやすくなるだけでなく、面倒な作業になります。
ContextDecoratorが機能する方法の一部としてタイムアウトを含めるためには、どのようにして希望の機能を実現できますか?
Python 3.6.1と最新のTornado(4.5.1)を使用しています。