【问题标题】:How do I wait for two asynchronous downloads to finish via QNetworkAccessManager?如何通过 QNetworkAccessManager 等待两个异步下载完成?
【发布时间】:2021-01-25 18:22:47
【问题描述】:

===总结============================================

我使用 QNetworkAccessManager 和 QNetworkRequests 来同时下载两个图像。如何确定两次下载已完成?

=== 详细说明================================

我有两张图片的 URL,我想异步下载它们。为此,我初始化 QNetworkAccessManager 并使用两个 QNetworkRequest。完成后,每个请求都会将图像的内容写入文件。

问题是两个请求彼此一无所知,因此无法验证另一个请求是否完成

您能告诉我如何等待两个请求都完成

完整代码如下:

import sys

from PyQt5.QtCore import QUrl, QFile, QIODevice
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest
from PyQt5.QtWidgets import QApplication, QWidget


class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()

        img_url1 = "https://somesite.com/image1.jpg"
        img_url2 = "https://somesite.com/image2.jpg"

        self.downloader = QNetworkAccessManager()

        self.requests = []
        self.temp_files = []

        for index, mediafile_url in enumerate([img_url1, img_url2]):
            self.requests.append(self.downloader.get(QNetworkRequest(QUrl(mediafile_url))))
            request = self.requests[index]

            self.temp_files.append(QFile(f'{mediafile_url.split("/")[-1]}'))
            temp_file = self.temp_files[index]

            request.finished.connect(lambda *args, r=request, tf=temp_file: self.download_image(r, tf))

        self.show()

    @staticmethod
    def download_image(request, temp_file):
        image_data = request.readAll()
        temp_file.open(QIODevice.WriteOnly)
        temp_file.write(image_data)
        temp_file.close()


app = QApplication(sys.argv)
window = MainWindow()
app.exec_()

【问题讨论】:

    标签: python pyqt pyqt5 qnetworkaccessmanager qnetworkrequest


    【解决方案1】:

    您必须创建一个跟踪下载的类:

    from dataclasses import dataclass
    import sys
    
    from PyQt5.QtCore import pyqtSignal, QObject, QUrl, QFile, QIODevice
    from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
    from PyQt5.QtWidgets import QApplication, QWidget
    
    
    @dataclass
    class DownloadRequest:
        url: QUrl
        filename: str
    
    
    class DownloadManager(QObject):
        finished = pyqtSignal()
    
        def __init__(self, parent=None):
            super().__init__(parent)
            self._manager = QNetworkAccessManager()
            self._pending_downloads = 0
    
            self.manager.finished.connect(self.handle_finished)
    
        @property
        def manager(self):
            return self._manager
    
        @property
        def pending_downloads(self):
            return self._pending_downloads
    
        def download(self, requests):
            for request in requests:
                qrequest = QNetworkRequest(request.url)
                qrequest.setAttribute(QNetworkRequest.User, request.filename)
                self.manager.get(qrequest)
                self._pending_downloads += 1
    
        def handle_finished(self, reply):
            self._pending_downloads -= 1
            if reply.error() != QNetworkReply.NoError:
                print(f"code: {reply.error()} message: {reply.errorString()}")
            else:
                print("successful")
                filename = reply.attribute(QNetworkRequest.User)
                file = QFile(filename)
                if file.open(QIODevice.WriteOnly):
                    file.write(reply.readAll())
    
            print(f"pending downloads {self.pending_downloads}")
            if self.pending_downloads == 0:
                self.finished.emit()
    
    
    class MainWindow(QWidget):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self._manager = DownloadManager()
            self._manager.finished.connect(self.handle_finished)
    
            img_url1 = "https://docs.python.org/3/_static/py.png"
            img_url2 = "https://somesite.com/image2.jpg"
    
            request1 = DownloadRequest(QUrl(img_url1), img_url1.split("/")[-1])
            request2 = DownloadRequest(QUrl(img_url2), img_url2.split("/")[-1])
    
            self._manager.download([request1, request2])
    
        def handle_finished(self):
            print("finished")
    
    
    def main():
        app = QApplication(sys.argv)
        window = MainWindow()
        window.show()
        app.exec_()
    
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-03
      • 2020-10-04
      • 2023-03-16
      • 1970-01-01
      • 2019-05-31
      • 2020-02-22
      • 2013-02-15
      • 1970-01-01
      相关资源
      最近更新 更多