如何在不阻塞 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")
我用 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")