简体   繁体   English

如何通过 QNetworkAccessManager 等待两个异步下载完成?

[英]How do I wait for two asynchronous downloads to finish via QNetworkAccessManager?

=== SUMMARY =========================================== ===总结===========================================

I use QNetworkAccessManager and QNetworkRequests to download two images simultaneously.我使用 QNetworkAccessManager 和 QNetworkRequests 同时下载两个图像。 How can I know for sure that two downloads finished?我如何确定两次下载已完成?

=== DETAILED DESCRITION =============================== === 详细说明 ===============================

I have URLs of two images and I want to download them asynchronously.我有两个图像的 URL,我想异步下载它们。 To do that I initialize QNetworkAccessManager and use two QNetworkRequests.为此,我初始化 QNetworkAccessManager 并使用两个 QNetworkRequest。 When finished, each request writes the contents of an image into a file.完成后,每个请求都会将图像的内容写入文件。

The problem is that both requests know nothing of each other and, therefore, cannot verify whether the other one is finished .问题是两个请求彼此一无所知,因此无法验证另一个请求是否已完成

Could you please tell me how can I wait for both requests to finish ?你能告诉我如何等待两个请求完成吗?

Here is the complete code:这是完整的代码:

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_()

You have to create a class that tracks downloads:您必须创建一个 class 来跟踪下载:

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我不等待的异步进程 - Asynchronous process that I do not wait for 如何继续迭代而不必等待输出完成? - How do I continue iterating without having to wait output to finish? 我如何等待 ThreadPoolExecutor.map 完成 - How do I wait for ThreadPoolExecutor.map to finish 如何显示循环中的数据但等待循环一一完成? - how do I display the data from the loop but wait for the loop to finish one by one? 如何等待子进程完成,存储其输出并在输出中添加前缀(没有新行)? - How do I wait for a subprocess to finish, store it's output and add a prefix (without a new line) to the output? 如何并行运行多个子进程并等待它们在 Python 中完成 - How do I run multiple subprocesses in parallel and wait for them to finish in Python 如何使用线程让一个动作等待另一个动作完成后再继续? - How do I use threads to make an action wait for another action to finish before moving on? 我如何完成这个ai? - How do I finish this ai? 如何让请求在 Python 中等待 302 重定向完成? - How can I make Requests wait for a 302 redirection to finish in Python? 我如何等待git clone在GitPython中完成 - How can I wait for a git clone to finish in GitPython
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM