PyQt SimpleHTTPServer:GUI 在启动服务器时冻结
PyQt SimpleHTTPServer: GUI freezes on starting server
我正在尝试使用 PyQt 创建一个简单的桌面应用程序,该应用程序在单击启动服务器按钮时运行 SimpleHTTPServer。我尝试过使用线程(python 线程和 Qthread)并理解这是不可能的,因为它遇到了 GIL 问题。这是代码
def btn_startserver_clicked(self):
server_thread=threading.Thread(target=start_server())
server_thread.start()
def start_server():
#to get server's IP
host=([(s.connect(('8.8.8.8', 80)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])
start=8000
end=56999
PORT = random.randint(start,end)
print host,":",PORT
httpd=ThreadedServer(("",PORT), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.handle_request()`
我尝试创建另一个进程,但发生了同样的事情。此外,如果我创建另一个进程,则每次服务请求时都会弹出一个新的 window。
def btn_startserver_clicked(self):
if __name__=='__main__':
server_process=Process(target=start_server())
server_process.start()
有什么办法解决这个问题吗?我觉得使用多处理是正确的方法,但我是新手,无法弄清楚为什么它仍然冻结。
谢谢
不确定您要做什么,但这可能有助于您入门:
import sys
from urllib.request import urlopen
from http.server import HTTPServer, SimpleHTTPRequestHandler
from PyQt4 import QtCore, QtGui
HOST, PORT = '127.0.0.1', 12345
class HttpDaemon(QtCore.QThread):
def run(self):
self._server = HTTPServer((HOST, PORT), SimpleHTTPRequestHandler)
self._server.serve_forever()
def stop(self):
self._server.shutdown()
self._server.socket.close()
self.wait()
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.button = QtGui.QPushButton('Start', self)
self.button.clicked.connect(self.handleButton)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.button)
self.httpd = HttpDaemon(self)
def handleButton(self):
if self.button.text() == 'Start':
self.httpd.start()
self.button.setText('Test')
else:
urlopen('http://%s:%s/index.html' % (HOST, PORT))
def closeEvent(self, event):
self.httpd.stop()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
您的示例锁定 GUI 的问题在于,您在创建线程时没有传递对函数的引用,实际上您立即 运行 函数并且永远不会创建线程。例如,您应该这样做:
server_thread=threading.Thread(target=start_server)
请注意,我将括号放在 start_server
上,否则代码会在创建 threading.Thread
对象之前等待 start_server()
完成执行,并使用来自 return 的值start_server()
作为 target
属性的值。
最后一个建议,你真的应该将创建的线程存储为 self.server_thread
以防止它被垃圾收集。
我正在尝试使用 PyQt 创建一个简单的桌面应用程序,该应用程序在单击启动服务器按钮时运行 SimpleHTTPServer。我尝试过使用线程(python 线程和 Qthread)并理解这是不可能的,因为它遇到了 GIL 问题。这是代码
def btn_startserver_clicked(self):
server_thread=threading.Thread(target=start_server())
server_thread.start()
def start_server():
#to get server's IP
host=([(s.connect(('8.8.8.8', 80)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])
start=8000
end=56999
PORT = random.randint(start,end)
print host,":",PORT
httpd=ThreadedServer(("",PORT), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.handle_request()`
我尝试创建另一个进程,但发生了同样的事情。此外,如果我创建另一个进程,则每次服务请求时都会弹出一个新的 window。
def btn_startserver_clicked(self):
if __name__=='__main__':
server_process=Process(target=start_server())
server_process.start()
有什么办法解决这个问题吗?我觉得使用多处理是正确的方法,但我是新手,无法弄清楚为什么它仍然冻结。
谢谢
不确定您要做什么,但这可能有助于您入门:
import sys
from urllib.request import urlopen
from http.server import HTTPServer, SimpleHTTPRequestHandler
from PyQt4 import QtCore, QtGui
HOST, PORT = '127.0.0.1', 12345
class HttpDaemon(QtCore.QThread):
def run(self):
self._server = HTTPServer((HOST, PORT), SimpleHTTPRequestHandler)
self._server.serve_forever()
def stop(self):
self._server.shutdown()
self._server.socket.close()
self.wait()
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.button = QtGui.QPushButton('Start', self)
self.button.clicked.connect(self.handleButton)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.button)
self.httpd = HttpDaemon(self)
def handleButton(self):
if self.button.text() == 'Start':
self.httpd.start()
self.button.setText('Test')
else:
urlopen('http://%s:%s/index.html' % (HOST, PORT))
def closeEvent(self, event):
self.httpd.stop()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
您的示例锁定 GUI 的问题在于,您在创建线程时没有传递对函数的引用,实际上您立即 运行 函数并且永远不会创建线程。例如,您应该这样做:
server_thread=threading.Thread(target=start_server)
请注意,我将括号放在 start_server
上,否则代码会在创建 threading.Thread
对象之前等待 start_server()
完成执行,并使用来自 return 的值start_server()
作为 target
属性的值。
最后一个建议,你真的应该将创建的线程存储为 self.server_thread
以防止它被垃圾收集。