Please consider the minimal example below, which implements a custom QNetworkAccessManager
that maintains a list of unfinished QNetworkReply
instances.
When a reply is finished
, it is removed from the unfinished_replies
list.
As discussed in Is deleteLater() necessary in PyQt/PySide?, QNetworkReply.deleteLater()
is used, inside the finished
slot, to schedule the Qt object for deletion.
However, I am not sure what would be the best way to remove the Python reference to the reply object. I can think of two (mutually exclusive) options for removing the Python reference, as shown in the example below:
remove directly after calling
deleteLater()
remove when the
QNetworkReply.destroyed
signal is emitted (docs)
Both options seem to work just fine. I would prefer option 1, but I'm not sure if this could lead to surprises in rare cases. Which would be best? Or is there another alternative?
import sys
from PyQt5 import QtNetwork, QtWidgets, QtCore
class CustomNetworkAccessManager(QtNetwork.QNetworkAccessManager):
def __init__(self):
super(CustomNetworkAccessManager, self).__init__()
self.unfinished_replies = []
self.finished.connect(self.slot)
def get(self, *args, **kwargs):
reply = super(CustomNetworkAccessManager, self).get(*args, **kwargs)
reply.index = i # just for printing
self.unfinished_replies.append(reply)
def remove_from_list(self, reply):
self.unfinished_replies.remove(reply)
print('{} unfinished replies left'.format(len(self.unfinished_replies)))
if not self.unfinished_replies:
QtCore.QCoreApplication.quit()
def slot(self, reply):
print('reply {} finished'.format(reply.index))
# handle the Qt side:
reply.deleteLater()
# handle the Python side:
# either
# OPTION 1 - remove now
self.remove_from_list(reply)
# or
# OPTION 2 - remove when destroyed
# reply.destroyed.connect(lambda: self.remove_from_list(reply))
if __name__ == '__main__':
# Initialize
app = QtWidgets.QApplication(sys.argv)
manager = CustomNetworkAccessManager()
# Schedule requests
url = 'http://httpbin.org/get'
for i in range(6):
manager.get(QtNetwork.QNetworkRequest(QtCore.QUrl(url)))
# Start event loop
app.exec_()
p.s. sorry for the Python 2 code