GUI Freezes while downloading PyQt5 and Pytube(GUI在下载PyQt5和Pytube时冻结)
                            本文介绍了GUI在下载PyQt5和Pytube时冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
                        
                        问题描述
我已经用Python制作了一个桌面应用程序,并使用了可以从YouTube下载视频的PyQt5和Pytube。当下载正在进行时,我想向用户显示动画。实际上我是这样做的,但是当文件正在下载时,PyQt窗口似乎冻结了,一切都会暂停,直到下载完成。有人知道为什么会发生这种事吗?我如何修复它?
以下是代码片段:
def download_created(self, qual): # Used in 'selection' method
    selected_stream = yt.streams.get_by_resolution(qual)
    self.progress_func()
    try:
        self.download_btn.setCurrentIndex(-1)
        selected_stream.download(self.askLocation() + "/")
    except:
        pass
    
# This gets the quality that the user chooses
def selection(self):
    global quality
    quality = self.download_btn.currentText()
    try:
        self.download_created(quality) # Calls a method called 'download'
    except:
        self.start_anime()
# Fetching the details about the Link from Youtube
def download_youtube(self):
    global check
    if check != self.get_input():
        check = self.get_input()
        self.download_btn.clear()
        enter_url = self.get_input()
        try:
            global yt
            yt = pytube.YouTube(
                enter_url,
                on_progress_callback = on_progress, 
                on_complete_callback = self.complete_func)
            
            self.start_anime()
        except:
            self.input_error()
        VIDEO_TITLE = (yt.title)
        global VIDEO_ID
        VIDEO_ID = (yt.video_id)
        videos = yt.streams.filter(mime_type="video/mp4", progressive="True")
        # Display all the available qualities
        for i in videos:
            self.download_btn.addItem(i.resolution)
        self.download_btn.currentIndexChanged.connect(self.selection)
推荐答案
您必须在另一个线程中执行耗时的任务,例如,在您的情况下,执行获取流和下载的任务。
import sys
import threading
from functools import cached_property
from PyQt5 import QtCore, QtWidgets
import pytube
class QPyTube(QtCore.QObject):
    initialized = QtCore.pyqtSignal(bool, str)
    download_started = QtCore.pyqtSignal()
    download_progress_changed = QtCore.pyqtSignal(int)
    download_finished = QtCore.pyqtSignal()
    def __init__(self, url):
        super().__init__()
        self._url = url
        self._yt = None
        self._mutex = threading.Lock()
        threading.Thread(target=self._init, daemon=True).start()
    @property
    def url(self):
        return self._url
    @cached_property
    def resolutions(self):
        return list()
    def _init(self):
        with self._mutex:
            self.resolutions.clear()
        try:
            self._yt = pytube.YouTube(
                self.url,
                on_progress_callback=self._on_progress,
                on_complete_callback=self._on_complete,
            )
            streams = self._yt.streams.filter(mime_type="video/mp4", progressive="True")
        except Exception as e:
            self.initialized.emit(False, str(e))
            return
        with self._mutex:
            self.resolutions = [stream.resolution for stream in streams]
        self.initialized.emit(True, "")
    def download(self, resolution, directory):
        threading.Thread(
            target=self._download, args=(resolution, directory), daemon=True
        ).start()
    def _download(self, resolution, directory):
        stream = self._yt.streams.get_by_resolution(resolution)
        self.download_started.emit()
        stream.download(directory)
    def _on_progress(self, stream, chunk, bytes_remaining):
        self.download_progress_changed.emit(
            100 * (stream.filesize - bytes_remaining) // stream.filesize
        )
    def _on_complete(self, stream, filepath):
        self.download_finished.emit()
class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.le_url = QtWidgets.QLineEdit("http://youtube.com/watch?v=2lAe1cqCOXo")
        self.lbl_error = QtWidgets.QLabel()
        self.btn_search = QtWidgets.QPushButton("Search")
        self.cmb_resolutions = QtWidgets.QComboBox()
        self.le_directory = QtWidgets.QLineEdit("")
        self.btn_download = QtWidgets.QPushButton("Download")
        self.pgb_download = QtWidgets.QProgressBar()
        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        lay = QtWidgets.QGridLayout(central_widget)
        lay.addWidget(self.le_url, 0, 0)
        lay.addWidget(self.btn_search, 0, 1)
        lay.addWidget(self.cmb_resolutions, 1, 0)
        lay.addWidget(self.le_directory, 1, 1)
        lay.addWidget(self.btn_download, 1, 2)
        lay.addWidget(self.pgb_download, 2, 0, 1, 3)
        self.btn_download.setEnabled(False)
        self._qpytube = None
        self.btn_search.clicked.connect(self.handle_search_clicked)
        self.btn_download.clicked.connect(self.handle_download_clicked)
    def handle_search_clicked(self):
        self.cmb_resolutions.clear()
        self.btn_search.setEnabled(False)
        self.btn_download.setEnabled(False)
        self.lbl_error.clear()
        self._qpytube = QPyTube(self.le_url.text())
        self._qpytube.initialized.connect(self.handle_initialized)
        self._qpytube.download_progress_changed.connect(self.pgb_download.setValue)
        self._qpytube.download_started.connect(self.handle_download_started)
        self._qpytube.download_finished.connect(self.handle_download_finished)
    @QtCore.pyqtSlot(bool, str)
    def handle_initialized(self, status, error=""):
        if status:
            self.cmb_resolutions.addItems(self._qpytube.resolutions)
            self.btn_download.setEnabled(True)
        else:
            self.lbl_error.setText(error)
        self.btn_search.setEnabled(True)
    def handle_download_clicked(self):
        self._qpytube.download(
            self.cmb_resolutions.currentText(), self.le_directory.text()
        )
        self.btn_search.setEnabled(False)
        self.btn_download.setEnabled(False)
        self.le_directory.setEnabled(False)
    def handle_download_started(self):
        self.lbl_error.clear()
        print("started")
    def handle_download_finished(self):
        self.pgb_download.setValue(100)
        self.btn_search.setEnabled(True)
        self.btn_download.setEnabled(True)
        self.le_directory.setEnabled(True)
        print("finished")
def main(args):
    app = QtWidgets.QApplication(args)
    w = MainWindow()
    w.show()
    app.exec_()
if __name__ == "__main__":
    main(sys.argv)
                        这篇关于GUI在下载PyQt5和Pytube时冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
				 沃梦达教程
				
			本文标题为:GUI在下载PyQt5和Pytube时冻结
				
        
 
            
        
             猜你喜欢
        
	     - 使用Heroku上托管的Selenium登录Instagram时,找不到元素';用户名'; 2022-01-01
 - 如何将一个类的函数分成多个文件? 2022-01-01
 - 沿轴计算直方图 2022-01-01
 - padding='same' 转换为 PyTorch padding=# 2022-01-01
 - pytorch 中的自适应池是如何工作的? 2022-07-12
 - 如何在 python3 中将 OrderedDict 转换为常规字典 2022-01-01
 - 分析异常:路径不存在:dbfs:/databricks/python/lib/python3.7/site-packages/sampleFolder/data; 2022-01-01
 - python check_output 失败,退出状态为 1,但 Popen 适用于相同的命令 2022-01-01
 - 如何在 Python 的元组列表中对每个元组中的第一个值求和? 2022-01-01
 - python-m http.server 443--使用SSL? 2022-01-01
 
				
				
				
				