python - 如何在 Python HTTPServer 中设置超时
问题描述
我有一个在 Debian 中运行的 Python (2.7.13) HTTP 服务器,我想停止任何花费超过 10 秒的 GET 请求,但在任何地方都找不到解决方案。
我已经尝试了以下问题中发布的所有片段:如何在 BaseHTTPServer.BaseHTTPRequestHandler Python 中实现超时
#!/usr/bin/env python
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os
class handlr(BaseHTTPRequestHandler):
def do_GET(self):
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())
def run():
server_address = ('127.0.0.1', 8080)
httpd = HTTPServer(server_address, handlr)
httpd.serve_forever()
if __name__ == '__main__':
run()
作为测试,我正在运行一个需要 20 秒才能执行的 shell 命令,因此我需要在此之前停止服务器。
解决方案
将您的操作放在后台线程上,然后等待后台线程完成。没有一种通用的安全方法来中止线程,所以不幸的是,这个实现让函数在后台运行,即使它已经放弃了。
如果可以的话,您可能会考虑nginx
在您的服务器前面放置一个代理服务器(例如 say )并让它为您处理超时,或者可能使用更健壮的 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()
推荐阅读
- r - 如何在 R 中读取 .mod 文件?
- python - 遍历行和列,python
- airflow - 如何将气流谱系导入图集?
- r - 使用 ggplot + gganimate 删除直线并将标签/标题设置为月份名称而不是数字
- pywinauto - Pywinauto - 如何等待具有相同窗口属性的窗口之间更改的特定窗口标题
- kubernetes - Kubernetes 入口编辑:HTTP 400 错误请求 - 纯 HTTP 请求已发送到 HTTPS
- javascript - 加载文件并解析文档
- spring-boot - Spring Boot -> UnsatisfiedDependencyException
- html - Bootstrap 自中心仅适用于某些元素
- java - 在 Oreo 版本中杀死 Android App 后每秒在后台运行 API