首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在图形用户界面中运行Python的SimpleHTTPServer

在图形用户界面中运行Python的SimpleHTTPServer
EN

Stack Overflow用户
提问于 2021-09-02 08:09:23
回答 1查看 571关注 0票数 0

我正在编写一个围绕Python的SimpleHTTPServer的图形用户界面包装器。它看起来是这样的:

图形用户界面使用tkinter。当我点击OK按钮时,它会启动web服务器。

web服务器代码基于https://docs.python.org/3/library/http.server.html上的文章。部分原因是:

代码语言:javascript
复制
with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()

到目前为止,一切都像预期的那样工作,但是当https.server_forever()函数运行时,我得到了旋转的beachball,并且我无法关闭窗口或退出。我可以强制退出,然后再试一次,这不方便。然而,服务器确实完成了它的工作。

如果我从命令行(非gui版本)运行相同的代码,我可以很容易地用ctrl-c中断它;我可以捕获它并更优雅地退出。

如何才能更礼貌地从服务器中断正在运行的服务器?

EN

回答 1

Stack Overflow用户

发布于 2021-09-02 18:35:42

您将需要在线程或单独的进程中运行服务器,因为web服务器和UI都需要单独的事件循环。

如果您希望服务器与tkinter程序进行通信,则需要设置一个队列。一般来说,您应该只从创建tkinter对象的线程访问tkinter对象。但是,我认为将虚拟事件从工作线程发送到GUI线程是安全的,您可以使用它使GUI线程从队列中读取数据。

例如,这是一个简单的线程化服务器。必须向其传递主机和端口、对根窗口的引用以及对队列的引用,在该队列中可以将信息发送到GUI。

代码语言:javascript
复制
class ExampleServer(threading.Thread):
    def __init__(self, host, port, gui, queue):
        threading.Thread.__init__(self)
        self.host = host
        self.port = port
        self.gui = gui
        self.queue = queue
        self.daemon = True

    def run(self):
        print(f"Listening on http://{self.host}:{self.port}\n")
        server = HTTPServer((self.host, self.port), ExampleHandler)
        server.serve_forever()

在请求处理程序中,可以将项推入队列,然后在根窗口上生成事件。它可能看起来像这样:

代码语言:javascript
复制
class ExampleHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        # handle the request
        ...

        # notify the UI
        self.queue.put("anything you want")
        self.gui.event_generate("<<DataAvailable>>")

您的gui还需要将队列作为参数,并需要设置虚拟事件的绑定。它可能看起来像这样:

代码语言:javascript
复制
class ExampleGUI(tk.Tk):
    def __init__(self, queue):
        super().__init__()
        self.queue = queue
        # set up the rest of the GUI
        ...

        # bind to the virtual event
        self.bind("<<DataAvailable>>", self.poll_queue)

    def poll_queue(self, event):
        while not queue.empty():
            data = self.queue.get_nowait()
            # Do whatever you need to do with the data
            ...

    def start(self):
        self.mainloop()

最后,您可以使用下面这样的代码将它们联系在一起:

代码语言:javascript
复制
if __name__ == "__main__":
    queue = queue.Queue()
    gui = ExampleGUI(queue)
    server = ExampleServer("localhost", 8910, gui, queue)
    server.start()
    gui.start()
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69026448

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档