Import multiple STL files and modify the incoming objects in one go? I want to import stl files using file browser (by using 'INVOKE_DEFAULT' on import stl operator). It seems that join() operator gets called before importing is finished. Does Blender import the objects in some kind of seperate thread to prevent a potential freeze?
I also tried macros but I'm getting the same result. join() operator gets called before the import is finished. I came across this method of window manager window_manager.fileselect_add() but couldn't get it to work. Sure, I can import the objects if that's finished, the user can join them but the client requires these two steps to be done using one single button.
import bpy


def main(context):
    for ob in context.scene.objects:
        print(ob)


class SimpleOperator(bpy.types.Operator):
    &quot;&quot;&quot;Tooltip&quot;&quot;&quot;
    bl_idname = &quot;object.simple_operator&quot;
    bl_label = &quot;Simple Object Operator&quot;

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}
    
    def invoke(self,context,event):
        return context.window_manager.fileselect_add(self)


def register():
    bpy.utils.register_class(SimpleOperator)


def unregister():
    bpy.utils.unregister_class(SimpleOperator)


if __name__ == &quot;__main__&quot;:
    register()


Q: Is there any way I can import and join the objects in one go?
Similar to Import STL via python, you can use the ImportHelper class if you'd like to import and modify objects. Have a look into the Operator File Import template that comes with Blender.
In order to join the objects, see @batFINGERs answer on: How to join objects with Python? How to import multiple objects using the file browser, you can find here: How to batch import Wavefront OBJ files?
# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# &lt;pep8 compliant&gt;


bl_info = {
    &quot;name&quot;: &quot;Custom Batch Import Stl (.stl)&quot;,
    &quot;author&quot;: &quot;brockmann&quot;,
    &quot;version&quot;: (0, 1, 0),
    &quot;blender&quot;: (2, 80, 0),
    &quot;location&quot;: &quot;File &gt; Import-Export&quot;,
    &quot;description&quot;: &quot;Import Stl files and join them&quot;,
    &quot;warning&quot;: &quot;&quot;,
    &quot;wiki_url&quot;: &quot;&quot;,
    &quot;tracker_url&quot;: &quot;&quot;,
    &quot;category&quot;: &quot;Import-Export&quot;}


import bpy
import os

from bpy_extras.io_utils import ImportHelper
from bpy.types import PropertyGroup
from bpy.props import StringProperty, CollectionProperty


class ImportSomeData(bpy.types.Operator, ImportHelper):
    &quot;&quot;&quot;Batch Import Stl files and join them&quot;&quot;&quot;
    bl_idname = &quot;import_scene.custom_stls&quot;
    bl_label = &quot;Import multiple OBJ's&quot;
    bl_options = {'PRESET', 'UNDO'}

    # ImportHelper mixin class uses this
    filename_ext = &quot;.stl&quot;

    filter_glob: StringProperty(
            default=&quot;*.stl&quot;,
            options={'HIDDEN'},
            )

    # Selected files
    files: CollectionProperty(type=PropertyGroup)

    def execute(self, context):

        # Get the folder
        folder = os.path.dirname(self.filepath)
        
        obs = []
        # Iterate through the selected files
        for i in self.files:

            # Generate full path to file
            path_to_file = (os.path.join(folder, i.name))
            bpy.ops.import_mesh.stl(filepath=path_to_file)
            # Append Object(s) to the list
            obs.append(context.selected_objects[:])
            # Print the imported object reference
            print (&quot;Imported object:&quot;, context.object)
        
        # Join the objects based on: 
        # https://blender.stackexchange.com/a/133024/
        obs = [x for sublist in obs for x in sublist]
        c = {}
        c[&quot;object&quot;] = c[&quot;active_object&quot;] = context.object
        c[&quot;selected_objects&quot;] = c[&quot;selected_editable_objects&quot;] = obs
        bpy.ops.object.join(c)

        return {'FINISHED'}


# Only needed if you want to add into a dynamic menu
def menu_func_import(self, context):
    self.layout.operator(ImportSomeData.bl_idname, text=&quot;Stl Batch &amp; Join (.stl)&quot;)


def register():
    bpy.utils.register_class(ImportSomeData)
    bpy.types.TOPBAR_MT_file_import.append(menu_func_import)


def unregister():
    bpy.utils.unregister_class(ImportSomeData)
    bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)


if __name__ == &quot;__main__&quot;:
    register()

    # test call
    bpy.ops.import_scene.custom_stls('INVOKE_DEFAULT')

Note: If you get paid for that and my code got your job done, please consider making a donation here: https://www.blender.org/foundation/donation-payment/ to make up for that.