1
$\begingroup$

Blender ver 2.83 LTS.

Whenever I tried to run this script twice, it came out an error:

ERROR (bke.lib_id): C:\b\buildbot-worker-windows\windows_lts_283\blender.git\source\blender\blenkernel\intern\lib_id.c:342 id_us_min: ID user decrement error: OBNew_STL (from '[Main]'): 0 <= 0

I'm trying to delete the old STL object without selection or restarting the blender file. This error is driving me crazy but I have no idea handle it.

import bpy


new_stl_is_here = []


def new_stl():
    global new_stl_is_here
    #  get old object list
    old_obj_lst = []
    for j in bpy.data.objects:
        old_obj_lst.append(j)
    #  import a STL file
    bpy.ops.import_mesh.stl(filepath="C:\\xxx.stl")
    #  get new object list
    new_obj_lst = []
    for jj in bpy.data.objects:
        new_obj_lst.append(jj)
    #  new STL is in this list
    new_stl_is_here = list(set(new_obj_lst)-set(old_obj_lst))
    
    
def delete_old_stl():
    for jjj in bpy.data.objects:
        if jjj.name == "New_STL":
            bpy.data.objects["New_STL"].user_clear()
            bpy.data.orphans_purge()
    
    
def rename_stl(): 
    new_stl_is_here[0].name = "New_STL"
    new_stl_is_here[0].data.name = "New_STL_mesh"
    

new_stl()
delete_old_stl()
rename_stl()
$\endgroup$
1
  • $\begingroup$ I think you are trying to clear the users of an object that has no user. before the user_clear line try if jjj.users > 0. Also I would replace the name of the jjj variable by obj, it's more clear. $\endgroup$ – Gorgious Feb 21 at 10:49
1
$\begingroup$

Ditch global lists and use selection

After calling the import operator any newly imported objects are selected and make up the context.selected_objects list.

I don't have any multi-object stl files to test theory against, but will go thru the motions with a single object file.

With no current selection.

>>> C.selected_objects
[]

Import stl

>>> bpy.ops.import_mesh.stl(filepath="/home/batfinger/Desktop/untitled.stl")
Import finished in 0.0156 sec.
{'FINISHED'}

Newly imported object(s) (Have no examples of multi object stls)

>>> C.selected_objects
[bpy.data.objects['Untitled']]

Remove that import

>>> old_import = C.selected_objects
>>> while old_import:
...     D.objects.remove(old_import.pop())
...     
>>> C.selected_objects
[]

Import again

>>> bpy.ops.import_mesh.stl(filepath="/home/batfinger/Desktop/untitled.stl")
Import finished in 0.0140 sec.
{'FINISHED'}

>>> C.selected_objects
[bpy.data.objects['Untitled']]

Rename this time

>>> #and to rename
>>> for o in C.selected_objects:
...     o.name = "Foo"
...     
>>> C.selected_objects
[bpy.data.objects['Foo']]

What's the file looking like

>>> D.objects[:]
[bpy.data.objects['Camera'], bpy.data.objects['Foo'], bpy.data.objects['Lamp']]

Notes.

Basically think the remove method in question code is "icky", as also is keeping some global list with object references ... just asking for a crash.

Notice the way the objects were removed in python console code above. They are unlinked (de-usered) by default.

To use a list like so recommend only using names, or just not doing it that way.

Putting this into a script

Have made a version of the script using a custom property tag to "mark" any imported STL. And to keep the new, remove, rename order also looked at the name.. one thinks remove, new, rename makes more sense.. anyhow

import bpy

tag = 'IMPORTED_STL_OBJECT'

def new_stl(filepath):
    #  import a STL file
    bpy.ops.import_mesh.stl(filepath=filepath)
    #  get new object list
    # ops use context silly not to use it.
    # could do set before / after here too.
    for o in bpy.context.selected_objects:
        o[tag] = 1
        o.data[tag] = 1
    
    
def delete_old_stl(name="NewSTL"):
    stls = [o for o in bpy.data.objects
            if (name and o.name.startswith(name))
            and tag in o.keys()]
    while stls:
        bpy.data.objects.remove(stls.pop())
    stl_meshes = [m for m in bpy.data.meshes
            if (name and m.name.startswith(name))
            and tag in m.keys()]
    while stl_meshes:
        bpy.data.meshes.remove(stl_meshes.pop())
            
        
def rename_stl(name="NewSTL"): 
        stls = [o for o in bpy.data.objects
            if tag in o.keys()]
        for o in stls:
            o.name = name
            o.data.name = f"{name}_Mesh"
    

new_stl("/home/batfinger/Desktop/untitled.stl")
delete_old_stl()
rename_stl()
$\endgroup$
3
  • $\begingroup$ Thanks a lot, after tried your method things goes very well in script. Anyway... when I tried to do the same in addon, an error occurred: 'Context' object has no attribute 'selected_objects'. Maybe objects wouldn't be auto selected after import in addon? $\endgroup$ – Fischer Feb 21 at 15:24
  • $\begingroup$ Not the case if done correctly. Maybe related Suggest post how you are attempting to run this in an addon. You cannot simply import the code as above as an addon. $\endgroup$ – batFINGER Feb 21 at 15:35
  • $\begingroup$ See blender.stackexchange.com/questions/212545/… re importing STL files in an addon. $\endgroup$ – batFINGER Feb 21 at 15:39

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.