Is there some way to get information about the QNetworkAccessManager queue?

1.1k views Asked by At

From the Qt 4 docs:

Note: QNetworkAccessManager queues the requests it receives.

Now, there are two things I would like to be able to do (using PyQt):

  1. Check how many requests are in the QNetworkAccessManager's "internal" queue, waiting to be sent.
  2. Check how many requests have received an answer (i.e. count number of finished QNetworkReplies).

I assume this information must already be available to the QNetworkAccessManager internally, yet I have not been able to find a way to access it. I could not find anything in the Qt docs or elsewhere, but perhaps I am looking in the wrong place or using the wrong terminology.

Can someone tell me if Qt provides some way to access information about the QNetworkAccessManager queue?

Just for clarity: I can think of a few ways to keep track of these things myself, e.g. by checking individual QNetworkReply states, but that's not the kind of solution I am looking for (only as a last resort, if Qt does not provide an easier way).

--- EDIT ---

A slightly-less-than-minimal yet still trivial example of the kind of thing I had in mind:

import sys
import json
from PyQt4 import QtNetwork, QtGui, QtCore

def show_reply_content(reply):
    print 'url from reply content: {}'.format(
        json.loads(str(reply.readAll()))['url'])

    # Quit if all replies are finished
    reply.deleteLater()
    reply.manager().replies_unfinished -= 1
    if not reply.manager().replies_unfinished:
    app.quit()

# Some initialization
app = QtGui.QApplication(sys.argv)
manager = QtNetwork.QNetworkAccessManager()
manager.finished.connect(show_reply_content)

# Add counter as dynamic attribute (quick and dirty)
manager.replies_unfinished = 0

# Schedule some dummy requests
number_of_requests = 10
for i in range(number_of_requests):
    manager.get(QtNetwork.QNetworkRequest(
        QtCore.QUrl('http://httpbin.org/anything/{}'.format(i))))

    # Update counter
    manager.replies_unfinished += 1

# Start event loop
app.exec_()

In this case something like an allFinished signal from the manager would save me a couple of lines of code.

1

There are 1 answers

0
ekhumoro On BEST ANSWER

Qt does not provide a way to access the QNetworkAccessManager internal cache.

The QNetworkReply APIs provide a relatively simple way to monitor the status of replies, but that does require the user to manage the replies themselves and keep a tally of what has been requested vs what has been received.

The QNetworkAccessManager.finished() signal is a fire-and-forget API that doesn't require management of the individual replies - however, there is no corresponding global signal that informs the user when all replies have been received.

The Qt docs are somewhat misleading with regard to the ownership of reply objects:

Note: After the request has finished, it is the responsibility of the user to delete the QNetworkReply object at an appropriate time.

This gives the impression that Qt does not maintain ownership of the replies, but in fact the QNetworkAccessManager makes itself parent of all its repiles, so that is not the case.

Given that all replies have their manager as parent, there is a relatively simple solution available in PyQt for checking the status of all current replies. The slot connected to the manager's finished() signal could contain code like this:

def handle_finished(self, reply):
    data = reply.readAll()
    # do something with data...
    reply.deleteLater()
    if all(child.isFinished() for child in
           reply.manager().findChildren(QtNetwork.QNetworkReply)):
        print('all finished')