【发布时间】:2020-05-20 14:43:08
【问题描述】:
请考虑下面的最小示例,它实现了一个自定义QNetworkAccessManager,它维护了一个未完成的QNetworkReply 实例列表。
当回复为finished 时,将其从unfinished_replies 列表中删除。
如Is deleteLater() necessary in PyQt/PySide? 中所述,QNetworkReply.deleteLater() 用于在finished 槽内安排 Qt 对象的删除。
但是,我不确定删除 Python 对回复对象的引用的最佳方法是什么。我可以想到两个(互斥的)用于删除 Python 引用的选项,如下例所示:
调用
deleteLater()后直接删除在
QNetworkReply.destroyed信号发出时移除 (docs)
这两个选项似乎都可以正常工作。我更喜欢选项 1,但我不确定这是否会在极少数情况下导致意外。哪个最好?还是有其他选择?
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_()
附言对不起 Python 2 代码
【问题讨论】: