You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复PyQt6中subprocess+aria2c下载时GUI卡顿及进度条不更新问题

修复PyQt6中QThread调用aria2c导致GUI卡顿的问题

核心问题:错误启动QThread

你的代码中test方法直接调用down.run(),这会让DownThread的run()方法在GUI主线程中执行,而非后台线程。整个下载过程阻塞了GUI事件循环,导致进度条和标签完全无法更新,直到下载完成才恢复响应。

修复方法

将down.run()替换为down.start():

def test(self):
    self.progressbar.setValue(0)
    down = DownThread(self, url, "D:/downloads")
    down.update.connect(self.update_displays)
    down.start()  # 替换原来的 down.run()

start()是QThread的正确启动方式,它会创建独立的后台线程,并在该线程中执行run()方法,不会阻塞GUI主线程。

可选优化:提升子进程输出读取效率

原代码逐字符读取subprocess的stdout(char = output.read(1))效率极低,会导致后台线程频繁占用资源。可以改为按行读取,并优化subprocess的参数:

def run(self) -> None:
    self.total = 0
    res = requests.head(url)
    if res.status_code == 200 and (total := res.headers.get("Content-Length")):
        self.total = int(total)
    self.process = subprocess.Popen(
        BASE_COMMAND + [f"--dir={self.folder}", self.url],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        bufsize=1,  # 行缓冲
        text=True   # 直接返回字符串,无需手动decode
    )
    self.monitor()
    self.quit()

def monitor(self) -> None:
    self.start = self.elapsed = time.time_ns()
    self.downloaded = 0
    with self.process.stdout as output:
        # 迭代读取每行输出,直到进程结束
        for line in iter(output.readline, ''):
            self.line = line.strip()
            self.update_stats()
    self.finish()

这种方式减少了IO操作的次数,提升监控线程的运行效率。

修复进度条计算逻辑

原代码中进度条的计算方式存在逻辑错误,会导致下载接近完成时进度条仍停留在低百分比:

# 原错误代码
self.progressbar.setValue(100 * int(stats["downloaded"] / stats["total"] + 0.5))

改为先计算百分比再取整:

def update_displays(self, stats):
    # 修复进度条计算
    progress = int(100 * stats["downloaded"] / stats["total"] + 0.5)
    self.progressbar.setValue(progress)
    # 其余代码保持不变...

内容的提问来源于stack exchange,提问作者Ξένη Γήινος

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 22:25:57