Actualización de elementos de la GUI en PyQT MultiThreaded

Estuve investigando durante un tiempo para encontrar información sobre cómo hacer un progtwig de multiproceso utilizando PyQT, actualizando la GUI para mostrar los resultados .

Estoy acostumbrado a aprender con el ejemplo y no puedo encontrar (sí, estuve buscando durante varias semanas) ningún ejemplo simple de un progtwig que utiliza multihilo haciendo una tarea tan simple como, por ejemplo, conectarme a una lista de sitios www (5 hilos) y simplemente imprimir procesando URLs con código de respuesta.

¿Alguien podría compartir el código o enviarme un buen tutorial donde se explique dicho progtwig?

Aquí algunos ejemplos muy básicos.

Puede pasar referencias a elementos de GUI a subprocesos y actualizarlos en subproceso.

import sys import urllib2 from PyQt4 import QtCore, QtGui class DownloadThread(QtCore.QThread): def __init__(self, url, list_widget): QtCore.QThread.__init__(self) self.url = url self.list_widget = list_widget def run(self): info = urllib2.urlopen(self.url).info() self.list_widget.addItem('%s\n%s' % (self.url, info)) class MainWindow(QtGui.QWidget): def __init__(self): super(MainWindow, self).__init__() self.list_widget = QtGui.QListWidget() self.button = QtGui.QPushButton("Start") self.button.clicked.connect(self.start_download) layout = QtGui.QVBoxLayout() layout.addWidget(self.button) layout.addWidget(self.list_widget) self.setLayout(layout) def start_download(self): urls = ['http://google.com', 'http://twitter.com', 'http://yandex.ru', 'http://stackoverflow.com/', 'http://www.youtube.com/'] self.threads = [] for url in urls: downloader = DownloadThread(url, self.list_widget) self.threads.append(downloader) downloader.start() if __name__ == "__main__": app = QtGui.QApplication(sys.argv) window = MainWindow() window.resize(640, 480) window.show() sys.exit(app.exec_()) 

Nota para los editores: Los widgets de Qt no son seguros para subprocesos y no se debe acceder a ellos desde ningún subproceso que no sea el hilo principal (consulte la documentación de Qt para obtener más detalles). La forma correcta de usar hilos es a través de señales / ranuras, como muestra la segunda parte de esta respuesta.


Además, puede usar señales y ranuras para separar la interfaz gráfica de usuario y la lógica de la red.

 import sys import urllib2 from PyQt4 import QtCore, QtGui class DownloadThread(QtCore.QThread): data_downloaded = QtCore.pyqtSignal(object) def __init__(self, url): QtCore.QThread.__init__(self) self.url = url def run(self): info = urllib2.urlopen(self.url).info() self.data_downloaded.emit('%s\n%s' % (self.url, info)) class MainWindow(QtGui.QWidget): def __init__(self): super(MainWindow, self).__init__() self.list_widget = QtGui.QListWidget() self.button = QtGui.QPushButton("Start") self.button.clicked.connect(self.start_download) layout = QtGui.QVBoxLayout() layout.addWidget(self.button) layout.addWidget(self.list_widget) self.setLayout(layout) def start_download(self): urls = ['http://google.com', 'http://twitter.com', 'http://yandex.ru', 'http://stackoverflow.com/', 'http://www.youtube.com/'] self.threads = [] for url in urls: downloader = DownloadThread(url) downloader.data_downloaded.connect(self.on_data_ready) self.threads.append(downloader) downloader.start() def on_data_ready(self, data): print data self.list_widget.addItem(unicode(data)) if __name__ == "__main__": app = QtGui.QApplication(sys.argv) window = MainWindow() window.resize(640, 480) window.show() sys.exit(app.exec_())