First small Python script - how to get all objects in scene?

I want to remove all material slots of a material on every object in the scene, which would be done with bpy.context.selected_objects . Now I’m trying to figure out how to select every object in the scene. Could anybody help me out with this please :)?

Nevermind I got this figured out but now I need help with the loop ;P.

for (????) in bpy.context.selectable_objects
   bpy.ops.object.material_slot_remove()

This should be it, shouldn’t it? Just don’t know what to put in the (???) space.

Here is a way.


import bpy

for ob in bpy.data.objects:
    print (ob.name)
    try:
        ob.material_slot_remove()
        print ("removed material from " + ob.name)
    except:
        print (ob.name + " does not have materials.")

Remember, however, not all objects have materials. So you have to either check the object type or trap for errors as I have done.

In this case there is no reason to “select” anything. Selecting an object in Blender using the API is a “expensive” task and requires that you restore previous selection states. I try to do all object manipulations via direct manipulation of the bpy.data.objects interface without altering the selection. Fetching and manipulating objects by their name is my preferred method.


ob = bpy.data.objects["Cube"]
if ob != None:
    #Continue processing.
else:
   #Object does not exist.

This gives me the object named “Cube”. If ob is None then the object does not exist.

Sorry, but how do I call the operator in that case ?


ob = bpy.data.objects["Cube"]
ob.material_slot_remove()


results in this error message in 2.59:
AttributeError: ‘Object’ object has no attribute ‘material_slot_remove’

You made an assumption. Remember the Bad News Bears movie?

You assumed that ob was valid. So you operated on it but it was not valid, it was None. A None object has no attributes and throws errors when they are accessed.

Try this code instead.


import bpy

ob = bpy.data.objects["Cube"] 
if ob != None:
    ob.material_slot_remove()
else:
    print("Object does not exist.")

In Blender python coding, I find that when I ignore validating variable that I run into errors or buggy code. So you have to constantly examine variables to make sure they contain what your next code expects them to.

Seems I am missing something obvious, I still can’t get it to work. I tried the code fragment from post #3 on a cube named “Cube” with a material, so I did not do the check - of course I would in a project. With your latest script I am also getting the same error like before.

The problem is that material.slot.remove() is not available from bpy.data.objects[“Cube”]. Autocompletion also does not offer this operation - nor does it show other important operations like shade_smooth(), so currently it seems to me that those are only possible if the object is selected, but hopefully I am wrong on that, I would much prefer doing it like you suggested.

I have never used auto completion. That could be your problem. Just don’t use auto completion and type in what you want your code to do. I know you do not have to have the object selected to fetch it from memory.

You can use…

print(dir(myVar))

…to view all possible methods available for the variable ob. Examine the console for the display from the print statement.

Revised:


import bpy  

ob = bpy.data.objects["Cube"]
print (dir(ob))
if ob != None:     
    ob.material_slot_remove() 
else:     
    print("Object does not exist.")

So this code really works for you ? Sorry for asking that stupid question, but when I am executing this script that is the output I am getting:


['__doc__', '__module__', '__slots__', 'active_material', 'active_material_index', 'active_shape_key', 'active_shape_key_index', 'animation_data', 'animation_data_clear', 'animation_data_create', 'animation_visualisation', 'bl_rna', 'bound_box', 'children', 'closest_point_on_mesh', 'collision', 'color', 'constraints', 'copy', 'data', 'delta_location', 'delta_rotation_euler', 'delta_rotation_quaternion', 'delta_scale', 'dimensions', 'draw_bounds_type', 'draw_type', 'dupli_faces_scale', 'dupli_frames_end', 'dupli_frames_off', 'dupli_frames_on', 'dupli_frames_start', 'dupli_group', 'dupli_list', 'dupli_list_clear', 'dupli_list_create', 'dupli_type', 'empty_draw_size', 'empty_draw_type', 'empty_image_offset', 'field', 'find_armature', 'game', 'grease_pencil', 'hide', 'hide_render', 'hide_select', 'is_duplicator', 'is_modified', 'is_visible', 'layers', 'library', 'location', 'lock_location', 'lock_rotation', 'lock_rotation_w', 'lock_rotations_4d', 'lock_scale', 'material_slots', 'matrix_basis', 'matrix_local', 'matrix_world', 'mode', 'modifiers', 'motion_path', 'name', 'parent', 'parent_bone', 'parent_type', 'parent_vertices', 'particle_systems', 'pass_index', 'pose', 'pose_library', 'proxy', 'proxy_group', 'ray_cast', 'rna_type', 'rotation_axis_angle', 'rotation_euler', 'rotation_mode', 'rotation_quaternion', 'scale', 'select', 'shape_key_add', 'show_axis', 'show_bounds', 'show_name', 'show_only_shape_key', 'show_texture_space', 'show_transparent', 'show_wire', 'show_x_ray', 'soft_body', 'tag', 'time_offset', 'to_mesh', 'track_axis', 'type', 'up_axis', 'update_tag', 'use_dupli_faces_scale', 'use_dupli_frames_speed', 'use_dupli_vertices_rotation', 'use_fake_user', 'use_shape_key_edit_mode', 'use_slow_parent', 'use_time_offset_add_parent', 'use_time_offset_edit', 'use_time_offset_parent', 'use_time_offset_particle', 'user_clear', 'users', 'users_group', 'users_scene', 'vertex_groups']
Traceback (most recent call last):
  File "/Text", line 6, in <module>
AttributeError: 'Object' object has no attribute 'material_slot_remove'

Ah, I am getting the same error you are. I forgot about the material slots layer. So we have to write our own version of the bpy.ops.material_remove_slot().

Here is an example of removing a material slot from an object. You still need to filter if an object is the right type, however.


import bpy  

ob = bpy.data.objects["Cube"]
print (dir(ob.material_slots))
if ob != None:
    for mat_slot in ob.material_slots:
        mat = mat_slot.material
        mat.user_clear()
        bpy.data.materials.remove(mat)
else:     
    print("Object does not exist.")

I think we are treading on the edge of the API here. Material_Slots seem to be read-only without a remove() method. So even though we can remove the materials, the slots remain. A better approach might be to assign a single material to all objects. After all if you remove all materials what will you render? And if you still need to render you might as well have at least a single material on all the objects.

And the API is kicking back :eyebrowlift: - got some funny characters on that slot after I removed it with your script and a crash. Perhaps it is better to stick to the selection method.
Nonetheless this was very instructional - thanks for your help !

is not that the same problem with list of object ?

you cannot use the original list of object to delte objects cause the index will cnange !

may be make a temp ist of the mat and use that list to delte the objects may be!

happy 2.5