PyQt使用QThread信号传递时Windows用户配置文件大小计算结果异常问题
核心问题:信号参数类型溢出
你定义的size_ready = pyqtSignal(int)使用了PyQt默认的32位有符号整数类型,它的最大值仅为2^31 - 1 = 2147483647(约2GB)。Windows用户配置文件的大小几乎都会超过这个值,Python原生int支持任意长度不会溢出,所以控制台打印结果正确,但是信号发射时会强制转换为32位有符号整数,发生溢出截断,导致UI拿到的数值错误。
修复方案:把信号参数类型改为pyqtSignal(object)或者pyqtSignal('qint64'),支持64位整数:
# 修改TailleRep类中的信号定义即可 size_ready = pyqtSignal(object) # 或者明确指定64位整数类型 size_ready = pyqtSignal('qint64')
其他需要修复的潜在问题
1. 遍历文件夹时未处理权限异常
用户目录下存在大量系统保护的目录/文件,直接调用f.stat()会抛出权限异常,导致计算直接中断,结果偏小。需要在getFolderSize方法中捕获异常:
def getFolderSize(self, folder_path): total_size = 0 start_path = Path(os.path.join(folder_path, '.')) for f in start_path.glob('**/*'): try: if f.is_file(): total_size += f.stat().st_size except (PermissionError, OSError): # 跳过无权访问的路径 continue return total_size
2. 线程生命周期管理缺失
当前计算完成后子线程不会自动退出,多次点击按钮会生成大量残留线程,还可能出现前一次计算的结果覆盖后一次的问题。需要添加信号绑定,计算完成后自动退出线程、清理资源:
def GetSize(self): self.getSizeBtn.setEnabled(False) self.thread = QThread() self.worker = TailleRep(os.getenv('USERPROFILE')) self.worker.moveToThread(self.thread) self.thread.started.connect(self.worker.work) self.worker.size_ready.connect(self.size_ready) # 新增:计算完成后自动清理线程和worker资源 self.worker.size_ready.connect(self.thread.quit) self.worker.size_ready.connect(self.worker.deleteLater) self.thread.finished.connect(self.thread.deleteLater) self.thread.start()
3. 避免遍历Windows自引用Junction目录
Windows用户目录下存在很多自引用的Junction目录(比如Application Data),部分Python版本会将其识别为普通目录递归遍历,导致重复计算甚至死循环,可以添加判断跳过Junction:
def is_junction(path: Path) -> bool: try: return bool(os.readlink(path)) except OSError: return False def getFolderSize(self, folder_path): total_size = 0 start_path = Path(os.path.join(folder_path, '.')) for f in start_path.glob('**/*'): try: if is_junction(f): continue if f.is_file(): total_size += f.stat().st_size except (PermissionError, OSError): continue return total_size
内容的提问来源于stack exchange,提问作者galio
相关产品推荐
相关产品推荐

