PyQt SimpleHTTPServer: GUI зависает на стартовом сервере
Я пытаюсь создать простое настольное приложение, использующее 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 ответа
Проблема с вашими примерами, которые блокируют GUI, заключается в том, что вместо передачи ссылки на функцию при создании потока вы фактически запускаете функцию немедленно, а поток никогда не создается. Например, вы должны делать:
server_thread=threading.Thread(target=start_server)
Обратите внимание, что я опускаю скобки на start_server
в противном случае код ждет start_server()
закончить выполнение перед созданием threading.Thread
объект и использует возвращаемое значение из start_server()
в качестве значения для target
приписывать.
Последнее предложение, вы должны действительно сохранить созданный поток как self.server_thread
чтобы предотвратить его сборку мусора.
Не совсем уверен, что вы пытаетесь сделать, но это может помочь вам начать:
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_())