# Object transformations not applying when running Blender in batch mode

I have a list of translations and rotations from a rigid body calculation that I'd like to apply to an object using the frame_change_pre handler.

Both the translation/rotation text file and the script that defines the handler are stored in my .blend file. When I open the .blend file in Blender and render the animation, the script works as expected.

My problem is that when I run in batch mode using the command:
/path/to/blender tossTest.blend -b -s 1 -e 8 -a
the transformations aren't applying in the output.

The following listing is the python script, script.py.

import bpy
from mathutils import Matrix
from mathutils import Vector

# Create 'posList' from 'positionDataSmall.txt', which is
# a text file stored inside this .blend file.
posList=[]
text=bpy.data.texts['positionDataSmall.txt']

for i in range(1,15):
text.current_line_index=i
line=text.current_line.body
posList.append([float(v) for v in line.split(',')])

# The function that rotates and translates Suzanne using
# the position list array.
# Called by the handler.
def rotByIndex(n):
if n<0: n=0
if n>=len(posList): n=len(posList)-1

mr=Matrix((posList[n][4:7],
posList[n][7:10],
posList[n][10:13])).to_4x4()
vt=Vector(posList[n][1:4])
mt=Matrix.Translation(vt)
m=mt*mr

obj=bpy.data.objects['Suzanne']
obj.matrix_local=m

# The handler which gets called
def my_handler(scene):
bpy.data.objects['Suzanne'].select=True

rotByIndex(scene.frame_current-1)
scene=bpy.data.scenes['Scene']
scene.update()

bpy.app.handlers.frame_change_pre.append(my_handler)


And here's positionDataSmall.txt:

time,X,Y,Z,r11,r12,r13,r21,r22,r23,r31,r32,r33
0,0,0,0,1,0,0,0,1,0,0,0,1
0.1,-0.008852,0.17392,0.582415,0.937926,-0.024107,-0.345997,0.099391,0.974378,0.201766,0.332292,-0.223621,0.916284
0.2,-0.086264,0.395815,1.171942,0.813167,0.008713,-0.581965,0.179952,0.947084,0.2658,0.553515,-0.320867,0.768548
0.3,-0.208956,0.61547,1.709725,0.682634,0.027446,-0.730245,0.263186,0.922954,0.280871,0.681722,-0.383931,0.622778
0.4,-0.359143,0.832437,2.177802,0.559921,0.035089,-0.827802,0.347363,0.897075,0.273121,0.752213,-0.440487,0.490048
0.5,-0.517773,1.04868,2.556567,0.434674,0.045545,-0.899435,0.429578,0.867257,0.251652,0.791527,-0.495778,0.357337
0.6,-0.676588,1.264907,2.837416,0.301292,0.064759,-0.95133,0.506222,0.834588,0.217262,0.808053,-0.547058,0.218583
0.7,-0.835403,1.481143,3.020156,0.162968,0.092379,-0.982297,0.575247,0.799951,0.170788,0.801569,-0.592908,0.077121
0.8,-0.994218,1.697387,3.104786,0.023238,0.127698,-0.991541,0.634886,0.764235,0.113421,0.772239,-0.632158,-0.063431
0.9,-1.153033,1.913641,3.091307,-0.114327,0.16981,-0.978823,0.683614,0.728353,0.046628,0.720813,-0.663804,-0.199482
1,-1.311849,2.129903,2.979719,-0.246211,0.217638,-0.944465,0.720182,0.693225,-0.027883,0.648604,-0.687039,-0.327552
1.1,-1.470664,2.346174,2.770023,-0.369041,0.269958,-0.889343,0.743655,0.659749,-0.108203,0.557458,-0.701271,-0.444365
1.2,-1.629479,2.562454,2.462217,-0.479677,0.32543,-0.814865,0.753434,0.628783,-0.192277,0.449704,-0.706136,-0.546936
1.3,-1.788296,2.778741,2.056303,-0.575288,0.382638,-0.722933,0.749268,0.601116,-0.277952,0.328096,-0.701514,-0.632639
1.4,-1.947117,2.995036,1.552281,-0.653427,0.440118,-0.615897,0.731267,0.577455,-0.363034,0.195743,-0.687524,-0.699282


Some notes and things I've tried:

• Register is checked for script.py in the .blend file.
• Auto Run Python Scripts is checked and saved in the user preferences.
• I've tried placing -y among the command-line arguments
• I've tried storing script.py as an external file and loading it using -P script.py
• When I print the matrix m in rotByIndex, Blender shows that it's getting and updating the matrix appropriately in batch mode. So I know rotByIndex is being called on frame changes and that it has access to posList.

Does anybody know why my object isn't updating properly when not in the GUI?

• What about calling bpy.data.objects['Suzanne'].update() before scene.update()? Not sure, but maybe this will help. Jul 10 '15 at 7:38

From the API documentation:

By default handlers are freed when loading new files, in some cases you may wan’t the handler stay running across multiple files (when the handler is part of an addon for example).

For this the bpy.app.handlers.persistent decorator needs to be used.

import bpy
from bpy.app.handlers import persistent

@persistent