如何修复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,提问作者Ξένη Γήινος
相关产品推荐
相关产品推荐

