Script calculated multiple times on frame I have a simple script like this:
import bpy
frame = 0

def tester(scene):
    global frame
    frame = scene.frame_current
    print(frame)

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


It should print out the current frame. If I just play the animation, works as expected, but when I start rendering it gives back multiple numbers on each frame.
(I'm only using this script to demonstrate, the problem is occurring in a more complex script. But the anomaly is the same.)
I'm getting results during rendering like this:
1
0
1
1 
Saved: 'C:\......'
2
1
2
2
Saved: 'C:\......'
3
2
3
3
Saved: 'C:\......'

and so on...
Any guess why and how can I prevent this from happening? (I'm trying to insert an if statement that is prevening the recalculation of an already calculated frame, but this solution is way more hacky than it should be...)
Clean the handlers.
with no handlers appended at all, running question script will print the frame once.
There is only one function assigned
&gt;&gt;&gt; for f in bpy.app.handlers.frame_change_pre:
...     f.__name__, f.__module__
...     
('tester', '__main__')

running question script three more times
&gt;&gt;&gt; for f in bpy.app.handlers.frame_change_pre:
...     f.__name__, f.__module__
...     
('tester', '__main__')
('tester', '__main__')
('tester', '__main__')
('tester', '__main__')

will see frame printed 4 times. (One assumes you made an edit to get the -1)
Clear the handler.
Can clear all the functions assigned to a hander via
bpy.app.handlers.frame_change_pre.clear()  

to remove all the methods from each time you run script above.
Or iterate over appended funcions and remove those where f.__name__ == &quot;tester&quot; or by module if testing in text editor (__name__ == &quot;__main__&quot;)
When a handler is assigned a method via an addon, it can be appended in the register and removed in the unregister.  The namespace of the addon ensures its the same method both times  my_addon.foo_function  whereas when run from main thread &quot;__main__.foo_function&quot; is not seen as the same.
Example in console of removing any frame change pre handler function added via main thread.
&gt;&gt;&gt; fs2remove = [f for f in bpy.app.handlers.frame_change_pre
...     if f.__module__ == &quot;__main__&quot;]

&gt;&gt;&gt; fs2remove
[&lt;function tester at 0x7ffac5165ca0&gt;, &lt;function tester at 0x7ffac51659d0&gt;, &lt;function tester at 0x7ffac5165d30&gt;, &lt;function tester at 0x7ffac5165550&gt;, &lt;function tester at 0x7ffac5165700&gt;]
&gt;&gt;&gt; while fs2remove:
...     bpy.app.handlers.frame_change_pre.remove(fs2remove.pop())
...     
&gt;&gt;&gt; bpy.app.handlers.frame_change_pre[:]
[]