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

从logging.Handler向PySimpleGUI.Multiline写入时抛出异常

问题描述

我开发了一个包含按钮和Multiline组件的PySimpleGUI程序,点击按钮会触发一个执行数秒的方法(其中调用了GitPython相关方法)。为了让该方法持续将输出写入Multiline,我创建了Logger并添加了自定义OutputHandler:

class OutputHandler(logging.Handler):
    window: PySimpleGUI.Window

    def __init__(self, window: PySimpleGUI.Window):
        super().__init__(logging.DEBUG)
        self.window = window

    def emit(self, record):
        print(record.msg)
        self.window["-OUTPUT-"].print(record.msg)
        self.window.refresh()

Logger被传入该方法,方法的输出及GitPython的进度信息均通过此Logger输出。但目前偶尔会出现如下异常:

Exception in thread Thread-12 (pump_stream):
Traceback (most recent call last):
  File "...\Python310\lib\site-packages\git\cmd.py", line 142, in pump_stream
    handler(line)
  File "...\Python310\lib\site-packages\git\util.py", line 662, in handler
    return self._parse_progress_line(line.rstrip())
  File "...\Python310\lib\site-packages\git\util.py", line 648, in _parse_progress_line
    self.update(
  File "MyGitPythonApp.py", line 97, in update
    self.logger.info(message)
  File "...\Python310\lib\logging\__init__.py", line 1477, in info
    self._log(INFO, msg, args, **kwargs)
  File "...\Python310\lib\logging\__init__.py", line 1624, in _log
    self.handle(record)
  File "...\Python310\lib\logging\__init__.py", line 1634, in handle
    self.callHandlers(record)
  File "...\Python310\lib\logging\__init__.py", line 1696, in callHandlers
    hdlr.handle(record)
  File "...\Python310\lib\logging\__init__.py", line 968, in handle
    self.emit(record)
  File "MyGitPythonApp.py", line 29, in emit
    self.window["-OUTPUT-"].print(record.msg)
  File "...\Python310\lib\site-packages\PySimpleGUI\PySimpleGUI.py", line 3582, in print
    _print_to_element(self, *args, end=end, sep=sep, text_color=kw_text_color, background_color=kw_background_color, justification=justification,
  File "...\Python310\lib\site-packages\PySimpleGUI\PySimpleGUI.py", line 17678, in _print_to_element
    multiline_element.update(outstring, append=True, text_color_for_value=text_color, background_color_for_value=background_color, autoscroll=autoscroll,
  File "...\Python310\lib\site-packages\PySimpleGUI\PySimpleGUI.py", line 3442, in update
    starting_point = self.Widget.index(tk.INSERT)
  File "...\Python310\lib\tkinter\__init__.py", line 3767, in index
    return str(self.tk.call(self._w, 'index', index))
RuntimeError: main thread is not in main loop
The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "...\Python310\lib\threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "...\Python310\lib\threading.py", line 953, in run
    self._target(*self._args, **self._kwargs)
  File "...\Python310\lib\site-packages\git\cmd.py", line 148, in pump_stream
    raise CommandError([f"<{name}-pump>"] + remove_password_if_present(cmdline), ex) from ex
git.exc.CommandError: Cmd('<stderr-pump>') failed due to: RuntimeError('main thread is not in main loop')
  cmdline: <stderr-pump> git fetch -v --progress -- origin

请问该异常是什么原因导致的?

异常原因分析

这个异常的核心原因是子线程直接操作GUI组件:

  • PySimpleGUI底层基于tkinter,tkinter的GUI操作严格要求必须在**主线程(主事件循环所在线程)**执行,不允许子线程直接修改GUI元素。
  • GitPython在处理git fetch这类命令的进度信息时,会开启独立子线程(比如报错中的Thread-12 (pump_stream))来实时读取命令输出并处理进度。
  • 你的自定义OutputHandler在emit方法中直接调用self.window["-OUTPUT-"].print()更新Multiline组件,而这个emit方法是被GitPython的子线程触发的,相当于在子线程中执行了GUI更新操作,违反了tkinter的线程安全规则,因此抛出RuntimeError: main thread is not in main loop异常,进而引发GitPython的CommandError。

内容的提问来源于stack exchange,提问作者Christian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 14:40:56