我从net的一些示例创建了一个webserver类。在捕获KeyboardInterrupt时,脚本结束,但是在KeyboardInterrupt之后不执行命令行。尝试的代码如下

import threading
import time
import signal
from http.server import BaseHTTPRequestHandler, HTTPServer

class WebServer(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.host = "localhost"
        self.port = 8080

    def run(self):
        ws = HTTPServer((self.host, self.port), MyHander)
        print("WebServer started at Port:",self.port)
        try:
            ws.serve_forever()
        except KeyboardInterrupt:
            pass
        finally:
            ws.server_close()
            print("WebServer stopped")

class MyHander(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write(bytes("<html><head><title>https://pythonbasics.org</title></head>", "utf-8"))
        self.wfile.write(bytes("<p>Request: %s</p>" % self.path, "utf-8"))
        self.wfile.write(bytes("<body>", "utf-8"))
        self.wfile.write(bytes("<p>This is an example web server.</p>", "utf-8"))
        self.wfile.write(bytes("</body></html>", "utf-8"))

webServer = WebServer()
webServer.start()


按下控制C时输出

WebServer started at Port:
>>>  8080
KeyboardInterrupt
>>>


我刚刚开始python编码。请帮助

最佳答案

键盘中断不会通过signal包传递给主线程之外的线程。通常,这比您要实现的目标要复杂。如果要CTRL + C杀死webServer线程,则需要做两件事。

首先确保您的主线程确实结束。即如果您的主线程用完了要执行的代码并等待其他线程完成,则您基本上处于死锁状态。使用while循环很容易解决。

其次,处理主线程中的KeyboardInterrupt并使用该信号关闭其他线程。同样,我们只是将其添加到while循环中。

附带说明一下,似乎HTTPServer.shutdown挂起(至少在Windows上),代码看起来正确,但是我认为这可能是继承名称处理问题。为了解决这个问题,我绕过了.shutdown的调用,只是设置了手动终止服务器所需的属性。

import threading
import time
from http.server import BaseHTTPRequestHandler, HTTPServer
from time import sleep

class WebServer(threading.Thread):
    def __init__(self):
        super().__init__()
        self.host = "localhost"
        self.port = 8080
        self.ws = HTTPServer((self.host, self.port), MyHandler)

    def run(self):
        print("WebServer started at Port:", self.port)
        self.ws.serve_forever()

    def shutdown(self):
        # set the two flags needed to shutdown the HTTP server manually
        self.ws._BaseServer__is_shut_down.set()
        self.ws.__shutdown_request = True

        print('Shutting down server.')
        # call it anyway, for good measure...
        self.ws.shutdown()
        print('Closing server.')
        self.ws.server_close()
        print('Closing thread.')
        self.join()


class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write(bytes("<html><head><title>Title</title></head>", "utf-8"))
        self.wfile.write(bytes("<p>Request: %s</p>" % self.path, "utf-8"))
        self.wfile.write(bytes("<body>", "utf-8"))
        self.wfile.write(bytes("<p>This is an example web server.</p>", "utf-8"))
        self.wfile.write(bytes("</body></html>", "utf-8"))


if __name__=='__main__':
    webServer = WebServer()
    webServer.start()
    while True:
        try:
            sleep(1)
        except KeyboardInterrupt:
            print('Keyboard Interrupt sent.')
            webServer.shutdown()
            exit(0)



运行文件,访问http://localhost:8080/hello+world,然后发送CTRL + C如下所示:

(base) C:\Users\james>python serve.py
WebServer started at Port: 8080
127.0.0.1 - - [20/Nov/2019 12:53:16] "GET /hello+world HTTP/1.1" 200 -
Keyboard Interrupt sent.
Shutting down server.
Closing server.
Closing thread.

关于python - 在Windows上编码的python中未捕获KeyboardInterrupt,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58950268/

10-11 11:26