PyQt SimpleHTTPServer:GUI在启动服务器上冻结

时间:2015-05-05 15:52:43

标签: python multithreading pyqt multiprocessing simplehttpserver

我正在尝试使用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()`

我尝试创建另一个进程,但同样的事情发生了。此外,如果我创建另一个进程,每次提供请求时都会弹出一个新窗口。

def btn_startserver_clicked(self):
    if __name__=='__main__':
        server_process=Process(target=start_server())
        server_process.start()

这有什么办法吗?我觉得使用多处理是正确的方法,但我是新手,并且无法弄清楚为什么它仍然会冻结。

由于

2 个答案:

答案 0 :(得分:2)

锁定GUI的示例的问题在于,在创建线程时,不是传递对函数的引用,而是实际上立即运行函数,并且永远不会创建线程。例如,您应该这样做:

server_thread=threading.Thread(target=start_server)

请注意,我将括号放在start_server上,否则代码会在创建start_server()对象之前等待threading.Thread完成执行,并使用start_server()的返回值作为target属性的值。

最后一个建议,您应该将创建的线程存储为self.server_thread,以防止它被垃圾回收。

答案 1 :(得分:0)

不完全确定您要尝试做什么,但这可能有助于您开始使用:

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_())