Blender Python Script Issue: Edge Bevel Weight Attribute Not Found (original) (raw)

I want to write a script that adds a “Bevel Modifier” followed by a “Subdivision Surface Modifier” to selected objects, with the Bevel Modifier using “Weight” as its limit method. Here’s the code created with DeepSeek’s assistance:

import bpy

def add_modifiers():
    # Ensure object selection exists [6](@ref)
    if bpy.context.active_object is None:
        print("Please select an object first")
        return
    
    obj = bpy.context.object
    
    # Add Bevel Modifier [1,6](@ref)
    bevel_mod = obj.modifiers.new(name="BevelMod", type='BEVEL')
    bevel_mod.segments = 2           # Set segment count to 2
    bevel_mod.limit_method = 'WEIGHT' # Set limitation method to weight [2](@ref)
    bevel_mod.width = 0.1           # Default bevel width
    
    # Add Subdivision Surface Modifier [6,7](@ref)
    subsurf_mod = obj.modifiers.new(name="SubsurfMod", type='SUBSURF')
    subsurf_mod.levels = 2          # View subdivision levels = 2
    subsurf_mod.render_levels = 3    # Render subdivision levels = 3 [7](@ref)

# Execute function
add_modifiers()

It works.

Next, I want to add a test statement to the code that says: if all edges of the object do not have a chamfer weight greater than 0(edge_bevelweight(value>0)), then in the added chamfer modifier, the limiting mode is“Angle”.

import bpy

def add_modifiers():
    # Ensure object selection exists
    if bpy.context.active_object is None:
        print("Please select an object first")
        return
    
    obj = bpy.context.object
    
    # Check for edges with bevel weight >0
    has_edge_weight = any(edge.bevel_weight > 0 for edge in obj.data.edges)
    
    # Add Bevel Modifier and set parameters
    bevel_mod = obj.modifiers.new(name="BevelMod", type='BEVEL')
    bevel_mod.segments = 2
    bevel_mod.width = 0.1
    
    # Set limit method conditionally
    if has_edge_weight:
        bevel_mod.limit_method = 'WEIGHT'  # Use weight method when weights exist
    else:
        bevel_mod.limit_method = 'ANGLE'   # Fallback to angle method
    
    # Add Subdivision Surface Modifier
    subsurf_mod = obj.modifiers.new(name="SubsurfMod", type='SUBSURF')
    subsurf_mod.levels = 2
    subsurf_mod.render_levels = 3

# Execute function
add_modifiers()

This throws an error:

Python: Traceback (most recent call last):
  File "\Text.001", line 31, in <module>
  File "\Text.001", line 12, in add_modifiers
  File "\Text.001", line 12, in <genexpr>
AttributeError: 'MeshEdge' object has no attribute 'bevel_weight'

The root cause appears to be DeepSeek’s inability to locate the correct attribute name for edge bevel weights in Blender’s data structure.

According to Blender’s documentation (Edge Bevel Weight), there should be accessible weight data. What is the correct attribute name for storing edge bevel weights in Blender 4.2+?

Moved to Python Support

I can’t check your code now but at the first sight edge.bevel_weight is an operator, not the attribute.
The attribute is ‘bevel_weight_edge’.

bl

In my custom addons I often check edge bevels (but using bmesh because I need it while in edit mode), if in meanwhile nobody gives you more info I’ll share with you tomorrow (if I don’t forget it…).

Anyway, you can start looking at this:
https://blender.stackexchange.com/questions/323622/how-can-i-get-an-edges-bevel-weight-attribute-value-via-python

LazyNg (阿懶 LazyNg) May 19, 2025, 4:08pm 3

Thank you very much for your enthusiastic help and effective guidance. The code now can properly distinguish the Limit Method when creating a new bevel modifier based on edge bevel weights.

The code that works correctly is as follows.

import bpy

def get_bevel_weight(obj, edge_index):
    """Get bevel weight for specified edge"""
    original_mode = obj.mode
    bpy.ops.object.mode_set(mode='OBJECT')  # Ensure object mode for data access
    try:
        obj_data = obj.evaluated_get(bpy.context.evaluated_depsgraph_get()).data
        if 'bevel_weight_edge' in obj_data.attributes:
            attr = obj_data.attributes['bevel_weight_edge']
            return attr.data[edge_index].value
        else:
            return 0.0
    finally:
        bpy.ops.object.mode_set(mode=original_mode)  # Restore original mode

def add_modifiers():
    # Verify selected object exists
    if bpy.context.active_object is None:
        print("Please select an object first")
        return
    
    obj = bpy.context.object
    
    # Check all edges for bevel weights
    has_weighted_edges = False
    for edge_index in range(len(obj.data.edges)):
        weight = get_bevel_weight(obj, edge_index)
        if weight > 0.0:
            has_weighted_edges = True
            break  # Stop checking when weighted edge found
    
    # Add/configure bevel modifier
    bevel_mod = obj.modifiers.new(name="BevelMod", type='BEVEL')
    bevel_mod.segments = 2
    bevel_mod.width = 0.1
    
    # Set constraint method dynamically
    bevel_mod.limit_method = 'WEIGHT' if has_weighted_edges else 'ANGLE'

    # Add subdivision modifier
    subsurf_mod = obj.modifiers.new(name="SubsurfMod", type='SUBSURF')
    subsurf_mod.levels = 2
    subsurf_mod.render_levels = 3

# Execute function
add_modifiers()

As I tried to improve the code further, I ran into another problem.

To avoid repeatedly adding modifiers after re-executing the code, I ask DeepSeek to add conditionals:

  1. If “BevelMod” already exists, update its constraint method based on edge weights (existing logic)
  2. Skip adding “SubsurfMod” if it already exists

The code is as follows:

import bpy

def get_bevel_weight(obj, edge_index):
    """Gets the chamfer weight of the specified edge"""
    obj_data = obj.evaluated_get(bpy.context.evaluated_depsgraph_get()).data
    if 'bevel_weight_edge' in obj_data.attributes:
        attr = obj_data.attributes['bevel_weight_edge']
        return attr.data[edge_index].value
    else:
        return 0.0

def add_modifiers():
    # Ensure that the selected object exists
    if bpy.context.active_object is None:
        print("Please select the object first.")
        return
    
    obj = bpy.context.object
    
    # Check the bevel weights of all edges first
    has_weighted_edges = False
    for edge_index in range(len(obj.data.edges)):
        weight = get_bevel_weight(obj, edge_index)
        if weight > 0.0:
            has_weighted_edges = True
            break  # Stop checking immediately if weight edge is found
    
    # Handle bevel modifiers
    mod_name = "BevelMod"
    if mod_name in obj.modifiers:
        # The modifier already exists, updating only the Limit Method
        bevel_mod = obj.modifiers[mod_name]
        bevel_mod.limit_method = 'WEIGHT' if has_weighted_edges else 'ANGLE'
    else:
        # Create a new modifier and set the full parameters
        bevel_mod = obj.modifiers.new(mod_name, type='BEVEL')
        bevel_mod.segments = 2
        bevel_mod.width = 0.1
        bevel_mod.limit_method = 'WEIGHT' if has_weighted_edges else 'ANGLE'
    
    # Handle subdivision modifiers (created only when none exist) 
    subsurf_mod_name = "SubsurfMod"
    if subsurf_mod_name not in obj.modifiers:
        subsurf_mod = obj.modifiers.new(subsurf_mod_name, type='SUBSURF')
        subsurf_mod.levels = 2
        subsurf_mod.render_levels = 3

# Execute the function
add_modifiers()

However, the modified code fails to update the limited method when modifiers exist. The logic appears correct, but weighted edges don’t trigger “WEIGHT” constraint when modifiers are pre-existing.

I looked at the logic and conditionals in the code and couldn’t see the problem. Could you help me to correct the problem?

Finally, thank you very much for letting me quickly solve the problems that have been plaguing me for days.

I’m still unable to check your code properly, I’m glad you solved your first issue. Using handlers could be a little tricky (and potentially could drive to performance problems) so it needs a solid approach, don’t trust 100% AI solutions.
Just to start you could go more in deep with handlers, search for:
bpy.app.handlers.depsgraph_update_post
As soon as I can I will try your code to see if I can help you directly.

Hi, keeping unchanged your logic and code you can try this:

import bpy

def get_bevel_weight(obj, edge_index):
    """Get bevel weight for specified edge (access directly from obj.data)"""
    original_mode = obj.mode
    bpy.ops.object.mode_set(mode='OBJECT')
    try:
        mesh = obj.data
        if mesh.attributes and 'bevel_weight_edge' in mesh.attributes:
            attr = mesh.attributes['bevel_weight_edge']
            return attr.data[edge_index].value
        else:
            return 0.0
    finally:
        bpy.ops.object.mode_set(mode=original_mode)


def add_modifiers():
    # Verify selected object exists
    if bpy.context.active_object is None:
        print("Please select an object first")
        return
    
    obj = bpy.context.object
    
    # Check all edges for bevel weights
    has_weighted_edges = False
    for edge_index in range(len(obj.data.edges)):
        weight = get_bevel_weight(obj, edge_index)
        if weight > 0.0:
            has_weighted_edges = True
            break  # Stop checking when weighted edge found

    # Check if Bevel modifier exists
    bevel_mod = None
    for mod in obj.modifiers:
        if mod.type == 'BEVEL':
            bevel_mod = mod
            break

    if bevel_mod is None:
        bevel_mod = obj.modifiers.new(name="BevelMod", type='BEVEL')
        bevel_mod.segments = 2
        bevel_mod.width = 0.1
    
    # Set limit method dynamically
    bevel_mod.limit_method = 'WEIGHT' if has_weighted_edges else 'ANGLE'

    # Check if a Subsurf modifier already exists
    has_subsurf = any(mod.type == 'SUBSURF' for mod in obj.modifiers)
    if not has_subsurf:
        subsurf_mod = obj.modifiers.new(name="SubsurfMod", type='SUBSURF')
        subsurf_mod.levels = 2
        subsurf_mod.render_levels = 3

# Execute function
add_modifiers()

Since you launch it manually no events handlers are needed.
I tested it and it works.
If you want to go deeper in your ‘bpy python adventure’ you can refine it a little further as a further excercise/study. I’d add some checks and a basic error management (eg: what if you run it on a non-mesh object?) and turn it in a little addon form so you can add a custom operator to launch it directly by Blender UI and not from text editor.
Hope it helps.

LazyNg (阿懶 LazyNg) May 20, 2025, 3:06pm 6

Thanks a ton for your help – everything worked perfectly and the issue that was giving me trouble is finally fixed! This is awesome!

I’ll put together a small addon and integrate this code as one of its features. As for adding a custom operator in the UI, I still need to figure that part out later.

It might’ve been a small thing for you, but it meant a lot to me. Seriously grateful for your help – hope you have an awesome day!