0
$\begingroup$

For example, I am running this script:

import bpy
import bmesh

if bpy.context.mode != 'OBJECT':
    bpy.ops.object.mode_set()
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()

bpy.ops.mesh.primitive_circle_add(vertices=16, radius=1, fill_type='NGON')
bpy.context.object.name = 'AAA'
bpy.context.object.data.name = 'AAA.MESH'  

bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.mesh.primitive_circle_add(vertices=16, radius=1, fill_type='NGON')
bpy.context.object.name = 'BBB'
bpy.context.object.data.name = 'BBB.MESH'  

bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')

bpy.data.scenes[0].objects.unlink(bpy.data.objects['AAA'])
bpy.data.scenes[0].objects.unlink(bpy.data.objects['BBB'])

After running this script many manes, I have multiple hidden objects named 'AAA.001','AAA.002','BBB.001','BBB.002', etc

How can I get the full list of non-linked (hidden, invisible) objects with Blender Python API? I want to completely remove all of them. Thank you.

$\endgroup$
1
$\begingroup$

API method bpy.data.objects.remove(...)

A common theme in blender is using the remove(...) method of a collection to remove an item. Akin to removing from a list.

Quick test script, find all objects in blend with no users or hidden and add to a list named "trash"

Print then empty the trash.

import bpy

context = bpy.context

trash = [o for o in bpy.data.objects
        if o.hide or not o.users]
print([o.name for o in trash])       

while(trash):
    bpy.data.objects.remove(trash.pop())

The "trash" list after running question script 4 times.

['AAA.001', 'AAA.002', 'AAA.003',
 'BBB.001', 'BBB.002', 'AAA', 'BBB',
 'BBB.003']

Note: there will be no "unlinked" objects in the scene objects collection. Once unlinked AFAIK there is no way to determine from which scene they were once linked. There may be hidden objects in the scene objects collection. Code above will remove all hidden objects in blend.

Use object reference

Recommend you get out of the habit of referencing by index or name. eg after running an operator

bpy.context.object.name = 'AAA'
bpy.data.scenes[0].objects.unlink(bpy.data.objects['AAA'])

If there is an object named "AAA" still in blend, then the newly added primitive will be named "AAA.001" and so on... In most cases the scene you are interested in is the context scene.

Recommend instead using object reference

aaa = context.object
aaa.name = "AAA"  
scene.objects.unlink(aaa)

Before I get a comment "needs to be bpy.context.object" inferred I have variables defined for context be it context = bpy.context for testing where later can be pasted into operator def execute(self, context): method code, where the context argument passed is not necessarily bpy.context. And scene = context.scene.

$\endgroup$
  • $\begingroup$ Thank you @batFINGER for a clear and detailed response! $\endgroup$ – olbersia Feb 24 at 8:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.