0
$\begingroup$

I have a python file I am using in blender to load up an old file another script saved previously using save_as_mainfile(). I want to delete some objects from the scene, but for the purpose of this question I will try to delete them all. Here is the code.

bpy.ops.wm.open_mainfile(filepath=filename)
bpy.ops.object.select_all(action='DESELECT')
for ob in bpy.data.objects:
    ob.select = True
result = bpy.ops.object.delete()
print("{} objects remain because results={}".format(len(bpy.data.objects), result))

The result of running this is "35 objects remain because results={'CANCELLED'}" .. I do not know why the operation was cancelled, and I am hoping the len is 0. I have checked and I am in OBJECT mode (indeed trying to change modes gave me a poll error of some kind).

Thanks.

$\endgroup$
1
  • $\begingroup$ this appears to be something to do with running python operations directly after calling open_mainfile() ... If I load the file using open_mainfile() but comment out the other code, then run this manually at the python prompt once blender has opened I have no problems ... is there perhaps a ready event or something that I need to hook ? $\endgroup$
    – othane
    Jan 12, 2017 at 19:38

3 Answers 3

1
$\begingroup$

Instead of looping on all object you can do this:

bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)

If you want to delete some specific objects you can use the below script. I had a .blend file (provided below) which has three cubes Cube Cube.001 and Cube.002, in this script I deleted both Cube and Cube.001 where Cube.002 is not deleted.

import bpy

C = bpy.context
scene = C.scene
bpy.ops.object.select_all(action='DESELECT')
for ob in bpy.data.objects:
    if ob.name in ['Cube','Cube.001']:
        ob.select = True
        scene.objects.active = ob
bpy.ops.object.delete(use_global=False)

.blend file can be found here:

$\endgroup$
7
  • $\begingroup$ I have not tried this, but I will. The trouble with that solution though, is later I wish to refine the for loop to select objects based on their name. So I was hoping to find out what I am doing wrong rather than just hacking around the problem. $\endgroup$
    – othane
    Jan 12, 2017 at 11:47
  • $\begingroup$ @othane, I've updated my answer and provided another solution to pick certain objects that you want to delete. Please accept the answer and upvote it if it solved the problem. I've also provided a .blend file having the script :) $\endgroup$
    – Tak
    Jan 12, 2017 at 12:01
  • $\begingroup$ I have tried adding the ob to the scene then calling delete with use_global set False, but unfortunately that did not solve the problem. The output still reads "35 objects remain because results={'CANCELLED'}" $\endgroup$
    – othane
    Jan 12, 2017 at 19:29
  • $\begingroup$ Well, my answer definitely works as shown in the provided .blend file, this means that your script fails somewhere else. Could you provide your .blend file to be able to help you further? $\endgroup$
    – Tak
    Jan 12, 2017 at 22:24
  • $\begingroup$ I found that if you first try to load the file from the script like so bpy.ops.wm.open_mainfile(filepath=filename) then I found the delete is CANCELLED $\endgroup$
    – othane
    Jan 13, 2017 at 10:25
1
$\begingroup$

I found that I needed to add a persistent post loader callback to do the work in ... this seems to allow the scene to load properly before running the commands ... ie something like this

@persistent
def load_handler(dummy):
    # do the deletes here now everything is properly loaded up
    bpy.ops.object.select_all(action='DESELECT')
    for ob in bpy.data.objects:
        ob.select = True
    result = bpy.ops.object.delete()

bpy.app.handlers.load_post.append(load_handler)
bpy.ops.wm.open_mainfile(filepath=filename)

There may be other ways, but I need the code I call to work quite generically so this solved my problems well. I am however not clear on the whole load process and why it didn't work originally?

$\endgroup$
1
  • 1
    $\begingroup$ Its because you're using bpy.ops. When using operators in code the context has to be correct, among other things. That's why you were getting the polling error. $\endgroup$
    – cmomoney
    Jan 13, 2017 at 15:18
0
$\begingroup$

You should avoid using bpy.ops and try using a low-level approach:

for obj in bpy.data.objects:
    obj.user_clear # clear this object of users
    bpy.context.scene.objects.unlink(obj) # unlink the object from the scene
    bpy.data.objects.remove(obj) #delete the object from the data block
$\endgroup$

You must log in to answer this question.

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