基于BaseHTTPRequestHandler的Python HTTP服务器请求中断实现咨询
实现思路与代码示例
核心思路
利用Python信号机制设置中断标志,在耗时请求处理的关键节点定期检查该标志,触发时提前终止处理流程并返回响应,让服务器自动回到监听新请求的状态。
具体实现步骤
- 注册SIGINT信号处理器:捕获
Ctrl+C触发的SIGINT信号,设置全局中断标志。 - 在请求处理中插入标志检查:在耗时操作的循环或步骤中加入标志判断,一旦触发则立即终止当前处理。
- 重置中断标志:每次处理新请求前重置标志,避免影响后续请求的正常执行。
完整代码示例
import signal import time from http.server import BaseHTTPRequestHandler, HTTPServer # 全局中断标志 _interrupted = False def handle_sigint(signum, frame): global _interrupted _interrupted = True print("\nReceived SIGINT, stopping current request...") class LongRequestHandler(BaseHTTPRequestHandler): def do_POST(self): global _interrupted # 处理新请求前重置中断标志 _interrupted = False self.send_response(200) self.send_header('Content-type', 'text/plain') self.end_headers() try: # 模拟耗时数分钟的处理流程 for step in range(120): # 模拟2分钟的分步处理 if _interrupted: self.wfile.write(b"\nRequest interrupted by SIGINT") return # 替换为实际耗时操作 time.sleep(1) progress_msg = f"Processing step {step+1}/120\r\n".encode() self.wfile.write(progress_msg) self.wfile.flush() # 确保客户端实时接收进度 self.wfile.write(b"\nRequest completed successfully") except Exception as e: self.wfile.write(f"\nError occurred: {str(e)}".encode()) if __name__ == "__main__": # 注册SIGINT信号处理逻辑 signal.signal(signal.SIGINT, handle_sigint) server_address = ('', 8080) httpd = HTTPServer(server_address, LongRequestHandler) print(f"Server running on port 8080. Press Ctrl+C to interrupt current request.") try: httpd.serve_forever() except KeyboardInterrupt: print("\nServer shutting down...") httpd.shutdown()
关键说明
- 信号处理器仅做标志设置:信号处理函数不能执行复杂IO或阻塞操作,仅设置全局标志保证线程安全。
- 实时响应客户端:示例中用
self.wfile.flush()让客户端实时收到进度更新,中断时能立即看到终止提示。 - 适配单线程模型:BaseHTTPRequestHandler默认单线程处理请求,当前请求被中断后,
serve_forever()会自动回到监听状态等待下一个请求。
进阶优化(可选)
如果耗时操作无法拆分为可检查的步骤,可以将处理逻辑放到子线程中,用threading.Event替代全局标志,实现更灵活的中断控制,但核心逻辑仍是通过标志触发处理终止。
内容的提问来源于stack exchange,提问作者HiroIshida
相关产品推荐
相关产品推荐

