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

线程运行时访问内部更新变量:PySimpleGUI进度条适配难题

解决方案

核心思路

  1. 解决进度条实时更新问题:给window.read()添加超时时间,让GUI事件循环能定期轮询进度状态;同时用write_event_value主动向GUI发送进度更新事件,避免阻塞。
  2. 实现函数跨环境兼容:给通用函数设计可选的进度更新接口,GUI环境传入GUI更新逻辑,终端环境默认使用终端打印,彻底避免函数直接依赖PySimpleGUI对象。

重构后的完整代码

import threading
import time
import PySimpleGUI as sg

def general_long_function(progress_updater=None):
    # 默认进度更新器:终端打印进度信息
    def default_updater(bar_idx, text, current, max_val):
        print(f"进度条{bar_idx}: {text} | {current}/{max_val}")

    updater = progress_updater or default_updater

    # 初始化进度条状态
    updater(0, "Do Top loop", 0, 10)
    updater(1, "Inner Loop item 0", 0, 10)

    for i in range(10):
        updater(0, "Do Top loop", i+1, 10)
        for k in range(10):
            updater(1, f"Inner Loop item {k}", k+1, 10)
            print(f'i: {i} , k:{k}, currTest: Inner Loop item {k}')
            time.sleep(.02)
    
    # 任务结束后清空进度条
    updater(0, "", 0, 10)
    updater(1, "", 0, 10)
    print('finished')

############################# GUI 代码 #############################
def the_gui():
    sg.theme('Light Brown 3')

    layout = [
        [sg.Text('Click Go to start a long-running function call')],
        [sg.Text(size=(25, 1), key='-OUTPUT0-')],
        [sg.Text(size=(25, 1), key='-OUTPUT1-')],
        [sg.Text(size=(25, 1), key='-OUTPUT2-')],
        [sg.ProgressBar(10, 'h', size=(30, 20), k='-PROGBAR0-')],
        [sg.ProgressBar(10, 'h', size=(30, 20), k='-PROGBAR1-')],
        [sg.ProgressBar(100, 'h', size=(30, 20), k='-PROGBAR2-')],
        [sg.Button('Go'), sg.Button('Popup'), sg.Button('Exit')],
    ]

    window = sg.Window('Multithreaded Window', layout)

    # GUI专用进度更新器:通过write_event_value向主循环发送进度事件
    def gui_progress_updater(bar_idx, text, current, max_val):
        window.write_event_value('-PROGRESS_UPDATE-', (bar_idx, text, current, max_val))

    while True:
        # 设置10ms超时,让循环定期执行,实现进度实时更新
        event, values = window.read(timeout=10)
        if event in (sg.WIN_CLOSED, 'Exit'):
            print('exiting...')
            break
        if event == 'Go':
            print('adding thread')
            thread_id = threading.Thread(
                target=general_long_function,
                args=(gui_progress_updater,),
                daemon=True
            )
            thread_id.start()
        if event == 'Popup':
            sg.popup_non_blocking('This is a popup showing that the GUI is running', grab_anywhere=True)
        if event == '-PROGRESS_UPDATE-':
            bar_idx, text, current, max_val = values[event]
            window[f'-PROGBAR{bar_idx}-'].update(current, max_val)
            window[f'-OUTPUT{bar_idx}-'].update(text)

    window.close()

if __name__ == '__main__':
    # 可切换运行模式:注释掉一行即可
    # general_long_function()  # 终端模式运行
    the_gui()  # GUI模式运行
    print('Exiting Program')

关键改进点说明

  • 进度逻辑解耦:通用函数不再依赖全局变量或PySimpleGUI对象,通过可选参数progress_updater接收更新逻辑,终端环境默认用打印,GUI环境传入专用更新函数,完美实现跨环境兼容。
  • 实时进度刷新:GUI事件循环通过window.read(timeout=10)定期执行,配合write_event_value主动发送进度事件,彻底解决原代码中进度条仅在用户操作时更新的问题。
  • 代码简洁可靠:移除了冗余的全局变量,改用事件传递进度数据,逻辑更清晰,维护成本更低。

独立运行函数的方式

直接调用general_long_function()即可,此时会默认使用终端打印进度信息,无需依赖PySimpleGUI:

if __name__ == '__main__':
    general_long_function()  # 终端模式运行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:03:21