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

PySimpleGUI调用Blender渲染返回None,求非阻塞执行解决方案

PySimpleGUI执行Blender渲染命令返回None且窗口冻结问题解决

问题根源

  1. 路径引号冗余:你在命令列表里给带空格的路径手动加了双引号,但sg.execute_command_subprocess会自动处理含空格的路径参数,额外的引号会被系统识别为路径的一部分,导致Blender程序或.blend文件无法被正确找到,最终子进程启动失败返回None。
  2. 单次结果获取无效:sg.execute_get_results仅调用一次且timeout设为1秒,Blender渲染启动需要时间,第一次调用时进程还没输出内容,直接返回None;同时没有持续监听进程输出,也没利用窗口的超时机制实现非阻塞更新。
  3. 未维护非阻塞事件循环:原代码没有在事件循环中定期检查子进程状态,长时间任务会导致窗口失去响应。

修复方案

1. 清理命令参数中的多余引号

把cmd_list里所有路径的双引号去掉,比如:
原路径:'"C:\\Program Files\\Blender Foundation\\Blender 3.4\\blender.exe"'
改为:'C:\\Program Files\\Blender Foundation\\Blender 3.4\\blender.exe'

2. 用窗口超时监听实现非阻塞输出

修改事件循环,通过window.read(timeout=100)定期触发检查子进程的逻辑,持续读取输出直到进程结束,同时保证窗口不冻结。

修正后的完整代码

import PySimpleGUI as sg

layout = [
    [sg.Multiline(size=(110, 30), echo_stdout_stderr=True, reroute_stdout=True, autoscroll=True, background_color='black', text_color='white', key='-MLINE-')],
    [sg.T('Prompt> '), sg.Input(key='-IN-', focus=True, do_not_clear=False)],
    [sg.Button('Run', bind_return_key=True), sg.Button('Exit')]]

window = sg.Window('Realtime Shell Command Output', layout)
current_process = None  # 保存当前运行的子进程

while True:
    # 用timeout实现定期检查,避免窗口冻结
    event, values = window.read(timeout=100)
    
    if event in (sg.WIN_CLOSED, 'Exit'):
        # 退出前终止正在运行的进程
        if current_process and current_process.poll() is None:
            current_process.terminate()
        break
    
    elif event == 'Run':
        # 清理之前的进程(如果有的话)
        if current_process and current_process.poll() is None:
            current_process.terminate()
        
        # 去掉所有路径的多余引号
        cmd_list = [
            'C:\\Program Files\\Blender Foundation\\Blender 3.4\\blender.exe',
            '-b',
            'C:\\Users\\***\\Desktop\\blendertest\\Astor_Blue.blend',
            '-o',
            'C:\\Users\\***\\Desktop\\blendertest\\out\\Astor_Blue\\Astor_Blue.####',
            '-s', '50', '-e', '52', '-t', '6', '-a'
        ]
        print("执行命令:", " ".join(cmd_list))
        # 启动非阻塞子进程,管道输出
        current_process = sg.execute_command_subprocess(
            cmd_list[0], *cmd_list[1:], pipe_output=True, wait=False
        )
    
    # 定期检查子进程输出
    if current_process and current_process.poll() is None:
        # 持续读取输出,直到进程结束
        results = sg.execute_get_results(current_process, timeout=0)
        if results:
            stdout, stderr = results
            if stdout:
                print(stdout, end='')
            if stderr:
                print(stderr, end='')
    elif current_process and current_process.poll() is not None:
        # 进程结束,读取剩余输出
        results = sg.execute_get_results(current_process, timeout=0)
        if results:
            stdout, stderr = results
            if stdout:
                print(stdout, end='')
            if stderr:
                print(stderr, end='')
        print(f"进程结束,退出码:{current_process.returncode}")
        current_process = None

window.close()

关键说明

  • 非阻塞机制:通过window.read(timeout=100)让事件循环每隔100毫秒触发一次,既可以响应用户操作,又能定期检查子进程输出,避免窗口冻结。
  • 输出处理:每次检查时调用sg.execute_get_results读取进程的实时输出,确保渲染日志能实时显示在Multiline组件中。
  • 进程管理:维护current_process变量,在启动新进程前终止旧进程,退出程序时也会清理运行中的进程,避免资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 00:07:46