I'd suggest using handlers for this task. Below is a script that adds a full set of render handlers, and prints the current frame (if possible) and name of the handler when that event happenshandler fires.
import bpy frame_handlers = [name for name in dir(bpy.app.handlers) if name.startswith("render")] def handler_function(name): def handler(scene): print(name) f"{getattr(scene, 'frame_current', 'N/A')} : {name}") return handler for name in frame_handlers: handler = getattr(bpy.app.handlers, name, None) if isinstance(handler, islist): not None: handler.clear() # clear first for testing handler.append(handler_function(name)) System console output for a 2 frame animation render, must have started render with current frame set at 0. (v 2.91)
0 : render_init 1 : render_pre 1 : frame_change_pre 1 : frame_change_post Saved: '/tmp/0001.png' Time: 00:00.47N/A : render_stats (Saving: 00:00.03) 1 : render_post 1 : render_write 2 : render_pre 2 : frame_change_pre 2 : frame_change_post Saved: '/tmp/0002.png' Time: 00:00.38N/A : render_stats (Saving: 00:00.02) 2 : render_post 2 : render_write 0 : render_complete 0 : frame_change_pre 0 : frame_change_post