Apply modifiers via python

Hey there!
I try to apply modifiers but if a modifier is broken (missing object, source, target, ect), or turned off (show viewport or render is false) code stops because can’t apply.
Is there a way to skip such modifiers and move on with the rest of the code? :slight_smile:

Thank You for the answers in advance!

Hello, it should be relatively easy with a try: except somewhere, could you add your script to the thread ?

The script is rather large, but the section that fails is there:

                    # Apply all modifiers
                    for modifier in obj.modifiers:
                        bpy.context.view_layer.objects.active = obj  # Set the active object
                        bpy.ops.object.modifier_apply(modifier=modifier.name)

it’s pretty basic :slight_smile: and if i manually “apply all” in blender, then “blender” successfully skip the “invalid” modifires.

no wonder, you loop over modifiers and you change that value during the loop, because you are applying the modifier. So obj. modifiers has one object less in the next loop. You should either use a new variable(list) and loop only over that list or you apply always just the first modifier until no more modifiers exist (which makes sense).

yep i see what You mean and i already made something similar when the order of applying was important, but now this is not the case.
but now the problem is, there are modifiers they are broken by default (reasons as above) so no code will able to apply them because they were broken initally :stuck_out_tongue:

I still thought that over again, but still if i apply modifiers one by one, not sure how can i tell to script that skip a modifier if it’s not applyable.
It’s not enough to stop there, i have to skip non applicable modifiers and continue with the next applicable one.

You need something like:

broken_modifiers = []

while True:
    for modifier in obj.modifiers:
        # I just copied this from the original, does the obj really need to be reselected each time?
        bpy.context.view_layer.objects.active = obj

        if modifier.name in broken_modifiers:
          continue

        # assumes modifier_apply throws an exception if it fails, you should catch the real exception only
        try:
            bpy.ops.object.modifier_apply(modifier=modifier.name)
        except:
            broken_modifiers.append(modifier.name)
        finally:
            # restart the loop because obj.modifiers has changed
            break

    # if all that's left is no modifiers or broken ones, exit infinite loop
    if len(broken_modifiers) == len(obj.modifiers):
        break
1 Like

That’s the one i needed!
Thank You!

Another solution with an operator override.

import bpy

obj = bpy.data.objects["Cube"]

with bpy.context.temp_override(object=obj):
    i = 0
    while i < len(obj.modifiers):
        modifier_name = obj.modifiers[i].name
        try:
            bpy.ops.object.modifier_apply(modifier=modifier_name)
        except RuntimeError:
            i += 1

another way :

import bpy

obj = bpy.data.objects["Cube"]

with bpy.context.temp_override(object=obj):
    mod_names = [mod.name for mod in obj.modifiers]
    for mod_name in mod_names:
        try:
            bpy.ops.object.modifier_apply(modifier=mod_name)
        except RuntimeError:
            pass

Yep, those are also working well!
Thank You for the alternatives :slight_smile: