Operator(bpy_struct)

Basic Operator Example

This script shows simple operator which prints a message.

Since the operator only has an Operator.execute function it takes no user input.

The function should return {'FINISHED'} or {'CANCELLED'}, the latter meaning that operator execution was aborted without making any changes, and that no undo step will created (see next example for more info about undo).

Note

Operator subclasses must be registered before accessing them from Blender.

import bpy


class HelloWorldOperator(bpy.types.Operator):
    bl_idname = "wm.hello_world"
    bl_label = "Minimal Operator"

    def execute(self, context):
        print("Hello World")
        return {'FINISHED'}


# Only needed if you want to add into a dynamic menu.
def menu_func(self, context):
    self.layout.operator(HelloWorldOperator.bl_idname, text="Hello World Operator")


# Register and add to the view menu (required to also use F3 search "Hello World Operator" for quick access).
bpy.utils.register_class(HelloWorldOperator)
bpy.types.VIEW3D_MT_view.append(menu_func)

# Test call to the newly defined operator.
bpy.ops.wm.hello_world()

Modifying Blender Data & Undo

Any operator modifying Blender data should enable the 'UNDO' option. This will make Blender automatically create an undo step when the operator finishes its execute (or invoke, see below) functions, and returns {'FINISHED'}.

Otherwise, no undo step will be created, which will at best corrupt the undo stack and confuse the user (since modifications done by the operator may either not be undoable, or be undone together with other edits done before). In many cases, this can even lead to data corruption and crashes.

Note that when an operator returns {'CANCELLED'}, no undo step will be created. This means that if an error occurs after modifying some data already, it is better to return {'FINISHED'}, unless it is possible to fully undo the changes before returning.

Note

Most examples in this page do not do any edit to Blender data, which is why it is safe to keep the default bl_options value for these operators.

Note

In some complex cases, the automatic undo step created on operator exit may not be enough. For example, if the operator does mode switching, or calls other operators that should create an extra undo step, etc.

Such manual undo push is possible using the bpy.ops.ed.undo_push function. Be careful though, this is considered an advanced feature and requires some understanding of the actual undo system in Blender code.

import bpy


class DataEditOperator(bpy.types.Operator):
    bl_idname = "object.data_edit"
    bl_label = "Data Editing Operator"
    # The default value is only 'REGISTER', 'UNDO' is mandatory when Blender data is modified
    # (and does require 'REGISTER' as well).
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        context.object.location.x += 1.0
        return {'FINISHED'}


# Only needed if you want to add into a dynamic menu.
def menu_func(self, context):
    self.layout.operator(DataEditOperator.bl_idname, text="Blender Data Editing Operator")


# Register.
bpy.utils.register_class(DataEditOperator)
bpy.types.VIEW3D_MT_view.append(menu_func)

# Test call to the newly defined operator.
bpy.ops.object.data_edit()

Invoke Function

Operator.invoke is used to initialize the operator from the context at the moment the operator is called. invoke() is typically used to assign properties which are then used by execute(). Some operators don’t have an execute() function, removing the ability to be repeated from a script or macro.

When an operator is called via bpy.ops, the execution context depends on the argument provided to bpy.ops. By default, it uses execute(). When an operator is activated from a button or menu item, it follows the setting in UILayout.operator_context. In most cases, invoke() is used. Running an operator via a key shortcut always uses invoke(), and this behavior cannot be changed.

This example shows how to define an operator which gets mouse input to execute a function and that this operator can be invoked or executed from the Python API.

Also notice this operator defines its own properties, these are different to typical class properties because Blender registers them with the operator, to use as arguments when called, saved for operator undo/redo and automatically added into the user interface.

import bpy


class SimpleMouseOperator(bpy.types.Operator):
    """ This operator shows the mouse location,
        this string is used for the tooltip and API docs
    """
    bl_idname = "wm.mouse_position"
    bl_label = "Invoke Mouse Operator"

    x: bpy.props.IntProperty()
    y: bpy.props.IntProperty()

    def execute(self, context):
        # Rather than printing, use the report function,
        # this way the message appears in the header.
        self.report({'INFO'}, "Mouse coords are {:d} {:d}".format(self.x, self.y))
        return {'FINISHED'}

    def invoke(self, context, event):
        self.x = event.mouse_x
        self.y = event.mouse_y
        return self.execute(context)


# Only needed if you want to add into a dynamic menu.
def menu_func(self, context):
    self.layout.operator(SimpleMouseOperator.bl_idname, text="Simple Mouse Operator")


# Register and add to the view menu (required to also use F3 search "Simple Mouse Operator" for quick access).
bpy.utils.register_class(SimpleMouseOperator)
bpy.types.VIEW3D_MT_view.append(menu_func)

# Test call to the newly defined operator.
# Here we call the operator and invoke it,
# meaning that the settings are taken from the mouse.
bpy.ops.wm.mouse_position('INVOKE_DEFAULT')

# Another test call, this time call execute() directly with pre-defined settings.
bpy.ops.wm.mouse_position('EXEC_DEFAULT', x=20, y=66)

Calling a File Selector

This example shows how an operator can use the file selector.

Notice the invoke function calls a window manager method and returns {'RUNNING_MODAL'}, this means the file selector stays open and the operator does not exit immediately after invoke finishes.

The file selector runs the operator, calling Operator.execute when the user confirms.

The Operator.poll function is optional, used to check if the operator can run.

import bpy


class ExportSomeData(bpy.types.Operator):
    """Test exporter which just writes hello world"""
    bl_idname = "export.some_data"
    bl_label = "Export Some Data"

    filepath: bpy.props.StringProperty(subtype="FILE_PATH")

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

    def execute(self, context):
        file = open(self.filepath, 'w')
        file.write("Hello World " + context.object.name)
        return {'FINISHED'}

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


# Only needed if you want to add into a dynamic menu.
def menu_func(self, context):
    self.layout.operator_context = 'INVOKE_DEFAULT'
    self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator")


# Register and add to the file selector (required to also use F3 search "Text Export Operator" for quick access).
bpy.utils.register_class(ExportSomeData)
bpy.types.TOPBAR_MT_file_export.append(menu_func)


# Test call.
bpy.ops.export.some_data('INVOKE_DEFAULT')

Dialog Box

This operator uses its Operator.invoke function to call a popup.

import bpy


class DialogOperator(bpy.types.Operator):
    bl_idname = "object.dialog_operator"
    bl_label = "Simple Dialog Operator"

    my_float: bpy.props.FloatProperty(name="Some Floating Point")
    my_bool: bpy.props.BoolProperty(name="Toggle Option")
    my_string: bpy.props.StringProperty(name="String Value")

    def execute(self, context):
        message = "Popup Values: {:f}, {:d}, '{:s}'".format(
            self.my_float, self.my_bool, self.my_string,
        )
        self.report({'INFO'}, message)
        return {'FINISHED'}

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_props_dialog(self)


# Only needed if you want to add into a dynamic menu.
def menu_func(self, context):
    self.layout.operator(DialogOperator.bl_idname, text="Dialog Operator")


# Register and add to the object menu (required to also use F3 search "Dialog Operator" for quick access).
bpy.utils.register_class(DialogOperator)
bpy.types.VIEW3D_MT_object.append(menu_func)

# Test call.
bpy.ops.object.dialog_operator('INVOKE_DEFAULT')

Custom Drawing

By default operator properties use an automatic user interface layout. If you need more control you can create your own layout with a Operator.draw function.

This works like the Panel and Menu draw functions, its used for dialogs and file selectors.

import bpy


class CustomDrawOperator(bpy.types.Operator):
    bl_idname = "object.custom_draw"
    bl_label = "Simple Modal Operator"

    filepath: bpy.props.StringProperty(subtype="FILE_PATH")

    my_float: bpy.props.FloatProperty(name="Float")
    my_bool: bpy.props.BoolProperty(name="Toggle Option")
    my_string: bpy.props.StringProperty(name="String Value")

    def execute(self, context):
        print("Test", self)
        return {'FINISHED'}

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_props_dialog(self)

    def draw(self, context):
        layout = self.layout
        col = layout.column()
        col.label(text="Custom Interface!")

        row = col.row()
        row.prop(self, "my_float")
        row.prop(self, "my_bool")

        col.prop(self, "my_string")


# Only needed if you want to add into a dynamic menu.
def menu_func(self, context):
    self.layout.operator(CustomDrawOperator.bl_idname, text="Custom Draw Operator")


# Register and add to the object menu (required to also use F3 search "Custom Draw Operator" for quick access).
bpy.utils.register_class(CustomDrawOperator)
bpy.types.VIEW3D_MT_object.append(menu_func)

# Test call.
bpy.ops.object.custom_draw('INVOKE_DEFAULT')

Enum Search Popup

You may want to have an operator prompt the user to select an item from a search field, this can be done using bpy.types.Operator.invoke_search_popup.

import bpy
from bpy.props import EnumProperty


class SearchEnumOperator(bpy.types.Operator):
    bl_idname = "object.search_enum_operator"
    bl_label = "Search Enum Operator"
    bl_property = "my_search"

    my_search: EnumProperty(
        name="My Search",
        items=(
            ('FOO', "Foo", ""),
            ('BAR', "Bar", ""),
            ('BAZ', "Baz", ""),
        ),
    )

    def execute(self, context):
        self.report({'INFO'}, "Selected:" + self.my_search)
        return {'FINISHED'}

    def invoke(self, context, event):
        context.window_manager.invoke_search_popup(self)
        return {'RUNNING_MODAL'}


# Only needed if you want to add into a dynamic menu.
def menu_func(self, context):
    self.layout.operator(SearchEnumOperator.bl_idname, text="Search Enum Operator")


# Register and add to the object menu (required to also use F3 search "Search Enum Operator" for quick access).
bpy.utils.register_class(SearchEnumOperator)
bpy.types.VIEW3D_MT_object.append(menu_func)

# Test call.
bpy.ops.object.search_enum_operator('INVOKE_DEFAULT')

base class — bpy_struct

class bpy.types.Operator(bpy_struct)

Storage of an operator being executed, or registered after execution

bl_cursor_pending

Cursor to use when waiting for the user to select a location to activate the operator (when bl_options has DEPENDS_ON_CURSOR set) (default 'DEFAULT')

Type:

Literal[Window Cursor Items]

bl_description

(default “”, never None)

Type:

str

bl_idname

(default “”, never None)

Type:

str

bl_label

(default “”, never None)

Type:

str

bl_options

Options for this operator type (default set())

Type:

set[Literal[Operator Type Flag Items]]

bl_translation_context

(default “Operator”, never None)

Type:

str

bl_undo_group

(default “”, never None)

Type:

str

has_reports

Operator has a set of reports (warnings and errors) from last execution (default False, readonly)

Type:

bool

layout

(readonly)

Type:

UILayout

macros

(default None, readonly)

Type:

bpy_prop_collection[Macro]

name

(default “”, readonly, never None)

Type:

str

options

Runtime options (readonly, never None)

Type:

OperatorOptions

properties

(readonly, never None)

Type:

OperatorProperties

bl_property

The name of a property to use as this operators primary property. Currently this is only used to select the default property when expanding an operator into a menu.

Type:

str

report(type, message)

report

Parameters:
  • type (set[Literal[Wm Report Items]]) – Type

  • message (str) – Report Message, (never None)

is_repeat()

is_repeat

Returns:

result

Return type:

bool

classmethod poll(context)

Test if the operator can be called or not

Parameters:

context (Context) – (never None)

Return type:

bool

execute(context)

Execute the operator

Parameters:

context (Context) – (never None)

Returns:

result

Return type:

set[Literal[Operator Return Items]]

check(context)

Check the operator settings, return True to signal a change to redraw

Parameters:

context (Context) – (never None)

Returns:

result

Return type:

bool

invoke(context, event)

Invoke the operator

Parameters:
  • context (Context) – (never None)

  • event (Event) – (never None)

Returns:

result

Return type:

set[Literal[Operator Return Items]]

modal(context, event)

Modal operator function

Parameters:
  • context (Context) – (never None)

  • event (Event) – (never None)

Returns:

result

Return type:

set[Literal[Operator Return Items]]

draw(context)

Draw function for the operator

Parameters:

context (Context) – (never None)

cancel(context)

Called when the operator is canceled

Parameters:

context (Context) – (never None)

classmethod description(context, properties)

Compute a description string that depends on parameters

Parameters:
Returns:

result

Return type:

str

as_keywords(*, ignore=())
Returns:

A copy of the properties as a dictionary.

Return type:

dict[str, Any]

classmethod bl_rna_get_subclass(id, default=None, /)
Parameters:
  • id (str) – The RNA type identifier.

  • default (bpy.types.Struct | None) – The value to return when not found.

Returns:

The RNA type or default when not found.

Return type:

bpy.types.Struct

classmethod bl_rna_get_subclass_py(id, default=None, /)
Parameters:
  • id (str) – The RNA type identifier.

  • default (type | None) – The value to return when not found.

Returns:

The class or default when not found.

Return type:

type

classmethod poll_message_set(message, *args)

Set the message to show in the tool-tip when poll fails.

When message is callable, additional user defined positional arguments are passed to the message function.

Parameters:
  • message (str | Callable[..., str | None]) – The message or a function that returns the message.

  • args (Any) – A sequence of arguments to pass to message, if it’s a callable, otherwise argument is not available.

Inherited Properties

Inherited Functions

References