0

Blender完全加载后如何自动执行python脚本?

语境

我的脚本基于种子生成场景。我想创建几千张图像,但由于 Blender 在一百代左右后泄漏内存,所以一切都变得明显变慢并最终崩溃。我想通过每个会话只创建 x 个图像并在每次会话后完全重新启动 Blender 来缓解这个问题。

问题

如果我手动加载混合文件并单击脚本编辑器中的播放按钮,一切都会按预期工作。当我在启动后尝试调用脚本时,它在add_curve_spirals.py第 184 行崩溃,因为context.space_datais None.

由于手动启动脚本工作正常,问题在于 Blender 处于某种错误状态。使用或不使用 GUI ( --background) 启动它都不会影响这一点。

失败的解决方案

  • blender myfile.blend --python myscript.py在上下文完全准备好之前执行脚本,从而产生错误。
  • 使用处理程序延迟执行 ( bpy.app.handlers.load_post) 在完全加载文件后调用我的脚本,但上下文仍未准备好并产生错误。
  • 将 Blender 中的脚本设置为在启动时自动执行(文本/寄存器)也会产生错误。
  • 按照此处的建议,使用套接字稍后将命令发送到 Blender。等待传入命令的服务器脚本会在启动期间阻止 Blender 并阻止它完全加载,因此效果与直接执行脚本相同。
  • 使用定时事件 ( bpy.app.timers.register(render_fun, first_interval=10).

这些都是我发现的自动执行脚本的所有方法。在每种情况下,脚本似乎都执行得太早/处于错误状态,并且都以相同的方式失败。

我想强调脚本不是这里的问题。即使我可以解决特定的行,也可能会出现许多类似的问题,我不想重写我的整个脚本。那么在正确状态下自动调用它的最佳方法是什么?

4

1 回答 1

0

事实证明,问题在于执行上下文。这在手动调用定时事件后变得很清楚,例如,在场景完全加载后,定时事件仍然在错误的上下文中执行。

Since the crash happened in the add_curve_spirals addon, the solution was to provide a context override the the operator invokation. The rest of my script was not equally sensitive to the context and worked just fine.

It was not clear to me, how exactly I should override the context, but this works for now (collected from other parts of the internet, so I don't understand all details):

def get_context():
    # create a context that works when blender is executed from the command line.
    idx = bpy.context.window_manager.windows[:].index(bpy.context.window)
    window = bpy.context.window_manager.windows[idx]
    screen = window.screen
    views_3d = sorted(
            [a for a in screen.areas if a.type == 'VIEW_3D'],
            key=lambda a: (a.width * a.height))
    
    a = views_3d[0]
    # override
    o = {"window" : window,
         "screen" : screen,
         "area" : a,
         "space_data": a.spaces.active,
         "region" : a.regions[-1]
    }
    return o

Final invocation: bpy.ops.curve.spirals(get_context(), spiral_type='ARCH', radius = radius, turns = turns, dif_z = dif_z, ...

于 2022-02-04T10:55:14.540 回答