提问人:Nahuel Aguirre 提问时间:4/8/2023 更新时间:4/14/2023 访问量:120
“如何使用yt-dlp api提供的下载百分比更新PyGtk中的进度条?”
"How to update a progress bar in PyGtk with the download percentage provided by the yt-dlp api?"
问:
我一直在用 python 编写一个小项目来练习 gui,但是我有点卡在处理 gtk 进度条的这一部分。 我认为问题与 yt-dlp 在开始下载时阻塞主线程有关,或者因为 gtk 不允许另一个线程修改自己的元素。 这是我的代码:
window.py
from downloader.download import Downloader
from time import sleep
import gi
import threading
# from multiprocessing import Process
from db.database import Data
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
class ProgressUpdate(threading.Thread):
def __init__(self, progress_bar, downloader):
super().__init__()
self.progress_bar = progress_bar
self.downloader = downloader
self.is_running = True
def stop(self):
self.is_running = False
def run(self):
while self.is_running:
percent = self.downloader.percent
print('Percent', percent)
if percent and percent != 0:
GLib.idle_add(self._update_progres_bar, percent)
sleep(0.5)
def _update_progress_bar(self, percent):
self.progress_bar.set_fraction(percent)
return False
class Window(Gtk.Window):
def __init__(self):
super().__init__(title="Downloader")
self.notebook = Gtk.Notebook()
self.add(self.notebook)
# Init conection with database
self.data = Data()
self.data.create_connection()
# Display page of window
self.display_download()
self.display_history()
self.link = ''
...
# more code
...
# callback function called when 'download' button is pressed
def __on_button_clicked(self, widget):
# Process for download
link = self.download_entry.get_text()
if link != "":
self.progress_bar.set_fraction(0)
downloader = Downloader()
updater = ProgressUpdate(self.progress_bar, downloader)
updater.start()
downloader.download(link) # Using yt-dlp
updater.stop()
self.progress_bar.set_fraction(1)
downloader.py
import yt_dlp as dl
# import os
LINK = ''
class Downloader:
def __init__(self):
self.status = ''
self.percent = None
# Clean percent value
def __clean_percent(self, percent):
for i, char in enumerate(percent):
if char == '%':
value = percent[i-5:i+1].replace('%', '')
break
try:
value = (float(value.replace(' ', '')) / 100)
except Exception as e:
print(e)
return value
def my_hook(self, d):
if d['status'] == 'downloading':
self.percent = self.__clean_percent(d['_percent_str'])
elif d['status'] == 'finished':
self.status = 'finished'
def download(self, link=LINK):
opts = {
'progress_hooks': [self.my_hook],
}
with dl.YoutubeDL(opts) as ytdl:
ytdl.download([link])
if __name__ == '__main__':
d = Downloader()
d.download()
我只想用下载百分比更新进度条。
答:
0赞
Gonzalo Odiard
4/14/2023
#1
基于您的代码的 gtk4 版本和有关 gtk https://pygobject.readthedocs.io/en/latest/guide/threading.html 上线程的文档
import threading
import time
import gi
import yt_dlp as dl
gi.require_version('Gtk', '4.0')
from gi.repository import GLib, Gtk, GObject
class Application(Gtk.Application):
def do_activate(self):
window = Gtk.ApplicationWindow(application=self)
self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.entry = Gtk.Entry()
self.box.append(self.entry)
self.button = Gtk.Button(label='Download')
self.button.connect('clicked', self.start)
self.box.append(self.button)
self.progress = Gtk.ProgressBar(show_text=True)
self.box.append(self.progress)
window.set_child(self.box)
window.present()
def update_progess(self, i):
self.progress.set_fraction(i)
return False
def dl_update_hook(self, dl):
percent = dl['_percent_str']
for i, char in enumerate(percent):
if char == '%':
value = percent[i-5:i+1].replace('%', '')
break
value = (float(value.replace(' ', '')) / 100)
GLib.idle_add(self.update_progess, value)
def start_download(self):
opts = {'progress_hooks': [self.dl_update_hook]}
url = self.entry.get_text()
with dl.YoutubeDL(opts) as ytdl:
ytdl.download([url])
def start(self, button):
print('Start!')
thread = threading.Thread(target=self.start_download)
thread.daemon = True
thread.start()
app = Application()
app.run()
评论