3
$\begingroup$

What interests me is basically to stop the execution of my code until the end of the render but at the same time view the progress of the render, considering that the possibility of the "ESC" key that cancels the render. I am looking on the internet but the situation is unclear to me, I found this:

Is it possible to make a sequence of renders and give the user the option to cancel the process through the UI at any given time?

but it seems quite complicated, I was wondering if there was a simpler solution to my specific case, as my situation is slightly different, as I don't want to render multiple.

Practically:

    ## my code
    ## my code
    bpy.ops.render.render('INVOKE_DEFAULT', animation = False, write_still = True)
    ## if render is done:
    ###### my code
    ###### my code
$\endgroup$
5
  • 1
    $\begingroup$ If you want to execute code when the rendering is completed you will have to use an application handler. $\endgroup$
    – Robert Gützkow
    Jan 16, 2020 at 18:45
  • $\begingroup$ @RobertGützkow Thanks, I was taking a look at this, but I don't really understand how to use them for my situation $\endgroup$
    – Noob Cat
    Jan 16, 2020 at 18:45
  • $\begingroup$ What particular aspect is unclear? You can write a function and then append it to bpy.app.handlers.render_post or bpy.app.handlers.render_complete as shown in the answer you've linked. Once the render is finished the function will be executed. $\endgroup$
    – Robert Gützkow
    Jan 16, 2020 at 18:48
  • $\begingroup$ @RobertGützkow Forgive me, I'm not very familiar with bpy.app.handlers and their management, I still have to learn a lot about it $\endgroup$
    – Noob Cat
    Jan 16, 2020 at 18:57
  • $\begingroup$ What if I have a for loop with the render as the final step, and I don't want another functon afterwards, just the loop to go into the next step? I can't find how to do this. $\endgroup$
    – J.Nada
    Aug 11, 2021 at 6:57

2 Answers 2

5
$\begingroup$

Blender's API documentation shows how to use the application handlers. In order to execute a function after rendering is complete, you can use one of the following two handlers:

  • bpy.app.handlers.render_post - Executed once after each rendered frame
  • bpy.app.handlers.render_complete - Executed once after all frames have been rendered

The function you want to execute is appended to the list of handler functions through append(some_function), where some_function is a reference to a function. It needs to take one argument, because an object of bpy.types.Scene will be passed to the function. Example:

def some_function(dummy):
    print("some function")

bpy.app.handlers.render_post.append(some_function)

If you later want to remove the function from the list of handlers, simply use remove(some_function). Example:

bpy.app.handlers.render_post.remove(some_function)

import bpy

def some_function(dummy):
    print("some function")

def some_other_function(dummy):
    print("some other function")

# Will be executed once after each rendered frame
bpy.app.handlers.render_post.append(some_function)

# Will be executed once when the whole rendering process is completed
bpy.app.handlers.render_complete.append(some_other_function)

bpy.ops.render.render('INVOKE_DEFAULT', write_still = True) 
$\endgroup$
4
  • 1
    $\begingroup$ Thanks to your answer I understood a lot of what I have to do. In your opinion, can I put bpy.app.handlers.render_complete.remove (my_function) inside my_function? It seems to be working, but I don't want to create possible crashes $\endgroup$
    – Noob Cat
    Jan 17, 2020 at 8:11
  • 2
    $\begingroup$ That should be completely fine. $\endgroup$
    – Robert Gützkow
    Jan 17, 2020 at 8:25
  • $\begingroup$ This brilliant answer should be a part of Blender documentation, i too found the blender docs pretty unclear especially in the aspect of how handlers are fired while rendering animation $\endgroup$
    – SourceCowD
    Mar 3, 2023 at 10:43
  • $\begingroup$ i wonder now when render_init gets called when rendering animation $\endgroup$
    – SourceCowD
    Mar 3, 2023 at 10:44
1
$\begingroup$

The strange thing is that rendering isn't actually complete in the render_complete handler. You can tell this if you create a timer in the render_complete handler and then put this in the timer:

if version >= 3300:
        if bpy.app.is_job_running('RENDER'):
            print('render has still not completed')
            return 0.0001

The timer wont start running until Blender returns to the main thread (cycles runs in it's own thread), and even then it will keep printing 'render has still not completed' for a short while.

This is problematic because it means you can't safely launch a new operator. I've also noticed that the timer intermittently doesn't even get created, any ideas why that could be?

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .