私はいくつかのシェルコマンドを実行するWebサーバーを持っています。このコマンドには通常数秒かかりますが、場合によってはそれ以上の時間がかかります。クライアント(Webブラウザやカールではありません)が切断されます。竜巻with_timeout正しい使用法
私はクライアントを修正する可能性がないので、サーバーを修正することを考えました。それは竜巻のフレームワークに基づいています。私はtornado.gen.with_timeout関数を使って書き換えましたが、何らかの理由で期待通りに動作しません。タイムアウトを5秒に設定したので、サーバに問い合わせるときに「X秒で終了」(X < 5)または「すでに5秒以上...まだ実行中」のいずれかを取得する予定です。どちらの場合も、私は5秒以内に応答を得ることを期待しています。ここで
はコードです:import os
import json
import datetime
import random
from tornado.ioloop import IOLoop
from tornado.web import RequestHandler, Application
from tornado.gen import coroutine, with_timeout, TimeoutError, Return
@coroutine
def run_slow_command(command):
res = os.system(command)
raise Return(res)
class MainHandler(RequestHandler):
@coroutine
def get(self):
TIMEOUT = 5
duration = random.randint(1, 15)
try:
yield with_timeout(datetime.timedelta(seconds=TIMEOUT), run_slow_command('sleep %d' % duration))
response = {'status' : 'finished in %d seconds' % duration}
except TimeoutError:
response = {'status' : 'already took more than %d seconds... still running' % TIMEOUT}
self.set_header("Content-type", "application/json")
self.write(json.dumps(response) + '\n')
def make_app():
return Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8080)
IOLoop.current().start()
そして、ここにカールから出力さ:
for i in `seq 1 5`; do curl http://127.0.0.1:8080/; done
{"status": "finished in 15 seconds"}
{"status": "finished in 12 seconds"}
{"status": "finished in 3 seconds"}
{"status": "finished in 11 seconds"}
{"status": "finished in 13 seconds"}
私が間違っているのは何?
これは機能しました。 'run_slow_command'コルーチンを完全に削除しました。(やはり' os.system'を囲むラッパーだけだったのですが)try ... except節で私は元のyieldを 'yield with_timeout(datetime.timedelta(seconds = TIMEOUT)サブプロセス(args =( 'sleep%d'%duration).split())。wait_for_exit()) ' – Graf