El hilandero de carga PyQt5 se detiene en la solicitud posterior

Estoy usando el QtWaitingSpinner que se encuentra aquí: https://github.com/snowwlex/QtWaitingSpinner . Puedes crear y comenzar un spinner así: spinner = QtWaitingSpinner(self); spinner.start() spinner = QtWaitingSpinner(self); spinner.start() . Desafortunadamente, cuando bash realizar una solicitud POST desde mi GUI, el control se detiene hasta que se devuelve una respuesta. Por consiguiente, no veo el girador en absoluto, o si lo hago prematuramente, deja de girar mientras espera la respuesta. Creo que tendré que usar algún tipo de método asíncrono como QThread o asyncio, pero no está claro cuál es la mejor manera de solucionar esto. Si alguien me puede mostrar la mejor manera de manejarlo, estaría agradecido. Aquí está una versión simplificada de lo que estoy haciendo:

 class Obj(QDialog): # some button calls this function when pressed def submit(self): #start spinner spinner = QtWaitingSpinner(self) spinner.start() # post some data to some url, spinner should spin r = requests.post('some_url.com', json=some_data) # stop spinner spinner.stop() 

El problema que está requests es bloquear el bucle Qt, por lo que elementos como QTimer no funcionan. Una solución es ejecutar esa tarea en otro subproceso, una forma sencilla de hacerlo es usar QRunnable y QThreadPool .

 class RequestRunnable(QRunnable): def __init__(self, url, json, dialog): QRunnable.__init__(self) self.mUrl = url self.mJson = json self.w = dialog def run(self): r = requests.post(self.mUrl, json=self.mJson) QMetaObject.invokeMethod(self.w, "setData", Qt.QueuedConnection, Q_ARG(str, r.text)) class Dialog(QDialog): def __init__(self, *args, **kwargs): QDialog.__init__(self, *args, **kwargs) self.setLayout(QVBoxLayout()) btn = QPushButton("Submit", self) btn.clicked.connect(self.submit) self.spinner = QtWaitingSpinner(self) self.layout().addWidget(btn) self.layout().addWidget(self.spinner) def submit(self): self.spinner.start() runnable = RequestRunnable("https://api.github.com/some/endpoint", {'some': 'data'}, self) QThreadPool.globalInstance().start(runnable) @pyqtSlot(str) def setData(self, data): print(data) self.spinner.stop() self.adjustSize() 

Un ejemplo completo se puede encontrar en el siguiente enlace.