Using Blender's filebrowser with Python

Every now and then an addon requires that the user selects a spe­cif­ic file or path. Sure, you could just give users a sim­ple string input and let them copy/paste into it but how much cool­er would it be to let them pick a file from the filebrowser?

Luckily Blender pro­vides a handy class that does almost every­thing for us.

Meet ImportHelper

Importhelper is a mix-in class found in the bpy_extras sub­mod­ule. It includes an invoke() func­tion that calls the file­brows­er and a few helper func­tions used in Blender’s importer addons. To use it all we have to do is extend it in our oper­a­tor. Let’s start by import­ing both ImportHelper and Operator.

from bpy_extras.io_utils import ImportHelper
from bpy.types import Operator

Now we can go ahead and cre­ate the operator:

class OT_TestOpenFilebrowser(Operator, ImportHelper):

    bl_idname = "test.open_filebrowser"
    bl_label = "Open the file browser (yay)"

    def execute(self, context):
        """Do something with the selected file(s)."""

        return {'FINISHED'}

Yup, that’s it. Our new oper­a­tor already has an invoke() func­tion that calls the file­brows­er and when a user selects a file, it stores the file’s path in self.filepath. Note that this is a reg­u­lar StringProperty inside ImportHelper that we inher­it­ed when we sub­classed it.


To fil­ter the types of files shown to the user we have to add a filter_glob prop­er­ty to our class. This is a StringProperty with the list of exten­sions we want to show. Each exten­sion is writ­ten in wild­card style and is sep­a­rat­ed by a semi-colon. Note that strings longer that 255 could be cut (since that’s the inter­nal buffer size). 

filter_glob: StringProperty(
    default='*.jpg;*.jpeg;*.png;*.tif;*.tiff;*.bmp',
    options={'HIDDEN'}
)

Also keep in mind that users can dis­able fil­ter­ing in the UI and select any kind of file. You might want to reject a file or do some­thing dif­fer­ent depend­ing on the exten­sion you receive. You can take care of that with good old spli­text().

filename, extension = os.path.splitext(self.filepath)

And what about adding set­tings to the file­brows­er screen? All you have to do is add prop­er­ties to the oper­a­tor as usu­al and they will show up in the browser.

    some_boolean: BoolProperty(
            name='Do a thing',
            description='Do a thing with the file you\'ve selected',
            default=True,
            )

Final code

import bpy
import os

from bpy.props import StringProperty, BoolProperty
from bpy_extras.io_utils import ImportHelper
from bpy.types import Operator


class OT_TestOpenFilebrowser(Operator, ImportHelper):

    bl_idname = "test.open_filebrowser"
    bl_label = "Open the file browser (yay)"
    
    filter_glob: StringProperty(
        default='*.jpg;*.jpeg;*.png;*.tif;*.tiff;*.bmp',
        options={'HIDDEN'}
    )
    
    some_boolean: BoolProperty(
        name='Do a thing',
        description='Do a thing with the file you\'ve selected',
        default=True,
    )

    def execute(self, context):
        """Do something with the selected file(s)."""

        filename, extension = os.path.splitext(self.filepath)
        
        print('Selected file:', self.filepath)
        print('File name:', filename)
        print('File extension:', extension)
        print('Some Boolean:', self.some_boolean)
        
        return {'FINISHED'}


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


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


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.test.open_filebrowser('INVOKE_DEFAULT')

There’s also an ExportHelper class that includes some util­i­ties to check for exist­ing files and set­ting a default unti­tled file­name in the browser. 

Did I miss some­thing? Let me know in the comments!

All the posts you can read
TutorialsBlender, Python03.04.2020