Please consider the minimal example below, which implements a custom QNetworkAccessManager
that maintains a list of unfinished QNetworkReply
instances.
Both are equivalent, they only differ the moment they are removed. But to understand more in detail you have to understand how the PyQt5/PySide2 binding works. Those libraries create a wrapper around the C++ object, something like:
class FooWrapper:
def __new__(self, cls, *args, **kwargs):
# ...
instance = ...
instance._cpp_object = create_cpp_object()
# ...
return instance
def foo_method(self, *args, **kwargs):
return execute_foo_method(self._cpp_object, *args, **kwargs)
def __del__(self):
destroyed_cpp_object(self._cpp_object)
So when calling deleteLater only the cpp_object is deleted and not the wrapper, you can verify that if you use:
reply.destroyed.connect(self.remove_from_list)
Traceback (most recent call last):
File "main.py", line 32, in <lambda>
reply.destroyed.connect(self.remove_from_list)
File "main.py", line 17, in remove_from_list
self.unfinished_replies.remove(reply)
ValueError: list.remove(x): x not in list
since the parameter passed by destroyed is an invalid wrapper getting the above error. For this case, a solution is to check if the cpp_object has been removed with sip.isdeleted():
from PyQt5 import QtNetwork, QtWidgets, QtCore
import sip
# ...
class CustomNetworkAccessManager(QtNetwork.QNetworkAccessManager):
# ...
def remove_from_list(self):
self.unfinished_replies = [
reply for reply in self.unfinished_replies if not sip.isdeleted(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:
reply.destroyed.connect(self.remove_from_list)
Returning to the study of your methods, these can be graphed as follows:
(FIRST METHOD)
------------┬------------------┬---------------------┬-----------------------
| | |
call_deleteLater remove_reply_from_list destroyed
(SECOND METHOD)
------------┬-----------------------------------------┬-----------------┬------
| | |
call_deleteLater destroyed remove_reply_from_list
And since you are using the original wrappers you should not have any problem.
Conclusion: Both are equivalent and safe.