如何在不阻塞 gui 的情况下从 Qt5 gui 打开 http.server?

How to open a http.server from a Qt5 gui without blocking the gui?

我用 Python 3.7 和 Qt5 做了一个 UI。

有一个按钮可以启动本地 http.server 并打开一个页面来显示一些报告数据。

问题是当我点击按钮时,它 运行 我的脚本,启动服务器并正确打开页面,但我的 ui 被阻止了。这就像在 ui 再次工作之前等待服务器完成其工作。

我读过多线程对 ui Tq 不好。有没有什么技巧可以独立于我的 ui 打开 http.server?

代码如果方法 运行 按按钮:

def OpenReport():
    class ReportHTTPHandler (http.server.SimpleHTTPRequestHandler):
        def run_cgi(self, reportclass):
            # Setup environment variables -
            _, _, query = self.path.partition ('?')

            os.environ['QUERY_STRING'] = query

            # Cookies
            co = filter (None, self.headers.get_all ('cookie', []))
            cookie_str = ', '.join (co)
            if cookie_str:
                os.environ['HTTP_COOKIE'] = cookie_str

            cgitb.enable ()

            f = io.StringIO ()
            with redirect_stdout (f):
                reportclass.runCGI (self)

            output = f.getvalue ()
            self.send_response (HTTPStatus.OK, '')
            self.flush_headers ()

            self.wfile.write (''.join (output).encode ())
            self.wfile.flush ()
            return

        def send_head(self):
            # Split the query string for parsing later
            path, _, query = self.path.partition ('?')
            # Check if URL is a report
            # This is not the neatest way
            if path == '/cgi/index.py':
                return ReportHTTPHandler.run_cgi (self, ReportIndex)
            elif path == '/cgi/facebook.py':
                return ReportHTTPHandler.run_cgi (self, ReportFacebook)
            elif path == '/cgi/google-map.py':
                return ReportHTTPHandler.run_cgi (self, ReportGoogleMap)
            elif path == '/cgi/instagram.py':
                return ReportHTTPHandler.run_cgi (self, ReportInstagram)
            elif path == '/cgi/linkedin.py':
                return ReportHTTPHandler.run_cgi (self, ReportLinkedIn)
            elif path == '/cgi/sms.py':
                return ReportHTTPHandler.run_cgi (self, ReportSMS)
            elif path == '/cgi/telegram.py':
                return ReportHTTPHandler.run_cgi (self, ReportTelegram)
            elif path == '/cgi/twitter.py':
                return ReportHTTPHandler.run_cgi (self, ReportTwitter)
            else:
                # Assume this is an asset
                return http.server.SimpleHTTPRequestHandler.send_head (self)


    port = 50000
    address = ("", port)
    server = http.server.HTTPServer

    handler = ReportHTTPHandler

    httpd = server (address, handler)
    print (f"Report tool server started on port {port}")
    webbrowser.open (f'http://localhost:{port}/cgi/index.py', new=2)

    try:
        httpd.serve_forever ()
    except KeyboardInterrupt:
        print ("\nKeyboard interrupt received, exiting.")
        sys.exit (0)

加载 ui 和 运行 服务器的代码:

# === Load the UI =========================================
gui = QtWidgets.QApplication([])
ui = uic.loadUi('ui/MyUI.ui')
ui.button_Report.clicked.connect(OpenReport)
ui.show()
gui.exec()

您可以在单击按钮时在线程中启动您的服务器,并将状态发回给您的 UI

def buttonClick(self):
   t = threading.Thread(target=self.startServer)
   t.start()

def startServer(self):
   *Launch Server
   self.progress_signal.emit("Complete")