Поместите свою операцию в фоновый поток, а затем дождитесь окончания фонового потока.Не существует универсального безопасного способа прерывания потоков, поэтому, к сожалению, эта реализация оставляет функцию работающей в фоновом режиме, даже если она уже перестала работать.
Если вы можете, вы можете рассмотреть возможность установки прокси-сервера(например, скажем nginx
) перед вашим сервером, и пусть он обрабатывает тайм-ауты для вас, или, возможно, используйте более надежную реализацию HTTP-сервера, которая позволяет это в качестве опции конфигурации.Но ответ ниже должен в основном покрыть это.
#!/usr/bin/env python
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os
import threading
class handlr(BaseHTTPRequestHandler):
def do_GET(self):
result, succeeded = run_with_timeout(lambda: os.popen('sleep 20 & echo "this took 20 seconds"').read(), timeout=3)
if succeeded:
self.send_response(200)
self.send_header('Content-type','text-html')
self.end_headers()
self.wfile.write(os.popen('sleep 20 & echo "this took 20 seconds"').read())
else:
self.send_response(500)
self.send_header('Content-type','text-html')
self.end_headers()
self.wfile.write('<html><head></head><body>Sad panda</body></html>')
self.wfile.close()
def run():
server_address = ('127.0.0.1', 8080)
httpd = HTTPServer(server_address, handlr)
httpd.serve_forever()
def run_with_timeout(fn, timeout):
lock = threading.Lock()
result = [None, False]
def run_callback():
r = fn()
with lock:
result[0] = r
result[1] = True
t = threading.Thread(target=run_callback)
t.daemon = True
t.start()
t.join(timeout)
with lock:
return tuple(result)
if __name__ == '__main__':
run()