PySide6中解决'Internal C++ object已删除'运行时错误方案
问题原因
你遇到的错误核心在于:每次创建LoggerWindow时,都会给根日志器添加一个新的QTextEditLogger处理器,但窗口销毁时没有移除这个处理器。当窗口通过deleteLater()彻底销毁后,处理器内的QPlainTextEdit对象已被删除,但根日志器仍持有该处理器的引用,后续日志输出时会尝试调用已销毁的对象方法,从而触发RuntimeError。
解决方案
核心修复逻辑是在窗口销毁时将对应的日志处理器从根日志器中移除,同时保留对窗口关闭的检测。以下是两种可行实现方式:
方式一:在closeEvent中先移除处理器再销毁窗口
修改LoggerWindow的closeEvent方法,先清理日志处理器,再执行窗口销毁操作:
def closeEvent(self, event): # 移除当前日志处理器,避免无效引用 logging.getLogger().removeHandler(self.logger_text_edit) # 执行窗口销毁 self.deleteLater() # 确认接受关闭事件 event.accept()
方式二:通过destroyed信号绑定处理器移除逻辑
如果依赖destroyed信号检测窗口关闭,可在窗口初始化时绑定信号槽,在销毁时自动清理处理器:
class LoggerWindow(QWidget): parent_dir = os.getcwd() def __init__(self): super().__init__() self.logger_text_edit = QTextEditLogger(self) self.logger_text_edit.setFormatter(logging.Formatter('[%(asctime)s %(levelname)s]: %(message)s')) logging.getLogger().addHandler(self.logger_text_edit) # 全局仅设置一次日志级别,避免重复操作 if logging.getLogger().level == logging.NOTSET: logging.getLogger().setLevel(logging.DEBUG) logging.info("Initialized") main_v_layout = QVBoxLayout() main_v_layout.addWidget(self.logger_text_edit.widget) self.setLayout(main_v_layout) # 绑定destroyed信号,窗口销毁时自动移除处理器 self.destroyed.connect(self._cleanup_log_handler) def _cleanup_log_handler(self): logging.getLogger().removeHandler(self.logger_text_edit) def closeEvent(self, event): self.deleteLater() event.accept()
额外优化建议
- 日志级别设置
logging.getLogger().setLevel(logging.DEBUG)只需执行一次,可放在MainWindow初始化或全局代码中,无需每次创建日志窗口重复设置。 - 若需频繁打开日志窗口,可考虑复用同一个
LoggerWindow实例(隐藏/显示而非重复创建),进一步简化处理器的管理逻辑。
内容的提问来源于stack exchange,提问作者HK51503
相关产品推荐
相关产品推荐

