请考虑下面的最小例子,它实现了一个自定义的^ {< CD1>},它维护未完成的^ {< CD2>}实例的列表。
当回复为finished
时,它将从unfinished_replies
列表中删除
正如在Is deleteLater() necessary in PyQt/PySide?中所讨论的,在finished
槽内使用QNetworkReply.deleteLater()
来调度Qt对象的删除
但是,我不确定删除对reply对象的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_()
另外,对于Python2代码,我很抱歉
两者都是等效的,它们只是在被移除时有所不同。但要更详细地理解,您必须了解PyQt5/PySide2绑定是如何工作的。这些库在C++对象周围创建包装器,例如:
因此,在稍后调用Delete时,仅删除cpp_对象,而不删除包装器,您可以验证是否使用:
因为destroyed传递的参数是获取上述错误的无效包装。对于这种情况,解决方案是检查是否已使用sip.isdeleted()删除cpp_对象:
回到对您的方法的研究,这些方法可以用图表表示如下:
而且,由于您使用的是原始包装,因此您应该不会有任何问题
结论:两者同等安全
相关问题 更多 >
编程相关推荐