Blender运行外部Python脚本调用transform.rotate报上下文错误
Blender命令行执行脚本调用rotate算子上下文错误解决方案
问题场景
- 运行环境:Windows 10、Blender 3.1.2
- 启动命令:
blender.exe test1.blend --python .\import.py - 实现目标:通过外部Python脚本启动Blender,导入数量不确定的.blend文件,设置文件内目标对象的位置与旋转参数
- 原测试脚本:
import bpy import os import math bpy.ops.wm.append( filepath=os.path.join('H:\\Python\\blender\\test2.blend', 'Object', 'Gear'), directory=os.path.join('H:\\Python\\blender\\test2.blend', 'Object'), filename='Gear' ) o = bpy.data.objects['Gear'] bpy.context.view_layer.objects.active = o bpy.ops.transform.rotate(value=3.14/4,orient_axis='Y') bpy.ops.transform.translate(value=(-4, 2, 5))
- 异常表现:test2.blend内Gear对象可正常导入,执行旋转操作时抛出如下错误,注释旋转代码行后平移操作可正常执行;Blender启动完成弹出报错提示后,将相同代码逐行粘贴到Blender内置Python控制台中可正常运行
Traceback (most recent call last): File "<string>", line 1, in <module> File "H:\Python\blender\.\import.py", line 19, in <module> bpy.ops.transform.rotate(value=2.0,orient_axis='Y') File "E:\Programme\Blender Foundation\Blender 3.1\3.1\scripts\modules\bpy\ops.py", line 132, in __call__ ret = _op_call(self.idname_py(), None, kw) RuntimeError: Operator bpy.ops.transform.rotate.poll() failed, context is incorrect
报错原因
bpy.ops系列算子强依赖Blender当前界面上下文状态,命令行传入--python参数时,脚本执行时机早于Blender 3D视图窗口完全初始化,3D视图上下文未就绪,transform.rotate算子的poll校验不通过。同版本下transform.translate算子的上下文校验逻辑更宽松,因此可以正常执行。Blender完全启动后手动粘贴代码到控制台时,3D视图上下文已加载完成,因此无报错。
解决方案
方案1:直接修改对象变换属性(优先推荐,适配批量处理场景)
完全绕开对bpy.ops算子和界面上下文的依赖,导入对象后直接赋值变换属性即可,稳定性最高,不受启动时机、界面状态影响,适配多文件批量导入处理需求:
import bpy import os import math # 可在此处扩展批量导入逻辑,遍历所有待处理blend文件路径即可 bpy.ops.wm.append( filepath=os.path.join('H:\\Python\\blender\\test2.blend', 'Object', 'Gear'), directory=os.path.join('H:\\Python\\blender\\test2.blend', 'Object'), filename='Gear' ) o = bpy.data.objects['Gear'] # 直接设置位置坐标,单位为米 o.location = (-4, 2, 5) # 欧拉角旋转模式下直接赋值XYZ轴弧度值,Y轴旋转45度对应值为math.pi/4 o.rotation_euler = (0, math.pi/4, 0)
注意:如果对象使用四元数旋转模式,替换为
o.rotation_quaternion赋值即可;轴角旋转模式则使用o.rotation_axis_angle赋值。
方案2:手动传入3D视图上下文调用算子
如果有特殊需求必须使用bpy.ops.transform系列算子,可手动查找3D视图区域构造合法上下文传入算子,绕开启动时上下文缺失问题:
import bpy import os import math bpy.ops.wm.append( filepath=os.path.join('H:\\Python\\blender\\test2.blend', 'Object', 'Gear'), directory=os.path.join('H:\\Python\\blender\\test2.blend', 'Object'), filename='Gear' ) o = bpy.data.objects['Gear'] bpy.context.view_layer.objects.active = o o.select_set(True) # 构造3D视图可用上下文 def build_3dview_context(target_obj): for window in bpy.context.window_manager.windows: for area in window.screen.areas: if area.type == 'VIEW_3D': for region in area.regions: if region.type == 'WINDOW': return { 'window': window, 'screen': window.screen, 'area': area, 'region': region, 'active_object': target_obj, 'selected_objects': [target_obj] } return None ctx = build_3dview_context(o) if ctx: bpy.ops.transform.rotate(ctx, value=math.pi/4, orient_axis='Y') bpy.ops.transform.translate(ctx, value=(-4, 2, 5))
方案3:延迟执行脚本到界面加载完成
通过Blender内置定时器,将变换操作延迟到Blender完全启动、界面上下文就绪后执行:
import bpy import os import math def exec_transform(): o = bpy.data.objects['Gear'] bpy.context.view_layer.objects.active = o o.select_set(True) bpy.ops.transform.rotate(value=math.pi/4, orient_axis='Y') bpy.ops.transform.translate(value=(-4, 2, 5)) return None bpy.ops.wm.append( filepath=os.path.join('H:\\Python\\blender\\test2.blend', 'Object', 'Gear'), directory=os.path.join('H:\\Python\\blender\\test2.blend', 'Object'), filename='Gear' ) # 延迟1秒执行,性能较差的机器可适当调大间隔值 bpy.app.timers.register(exec_transform, first_interval=1.0)
内容的提问来源于stack exchange,提问作者MasterFX
相关产品推荐
相关产品推荐

