How can I get the info message from a blender operator?

I have make an operator which is doing multiple actions. One of them is the bpy.ops.mesh.remove_doubles(). My problem is that I can’t find a way to get it’s message info. For example, if I use bpy.ops.mesh.remove_doubles() individually, when it finish I get an info message of how many vertices have been removed. How can I get this info message through my operator?

class FU3DM_OT_clear_imported_meshes(bpy.types.Operator):
    bl_idname = "fu3dm.clear_imported_meshes"
    bl_label = ""
    bl_description = "Clear Imported Meshes"

    def execute(self, context):
        bpy.ops.object.mode_set(mode='EDIT')
        bpy.ops.mesh.select_all(action='SELECT')
        bpy.ops.mesh.tris_convert_to_quads(face_threshold=3.14159, shape_threshold=3.14159)
        bpy.ops.mesh.remove_doubles()
        return {"FINISHED"}
1 Like

Most common technique is to flip editor type and copy contents.

import bpy

def get_report():
    # store it
    thiscontext = bpy.context.area.type
    # copy content
    bpy.context.area.type = 'INFO'
    bpy.ops.info.select_all(action='SELECT')
    bpy.ops.info.report_copy()
    bpy.ops.info.select_all(action='DESELECT')
    # restore
    bpy.context.area.type = thiscontext
    # transfer to clipboard
    clipboard = bpy.context.window_manager.clipboard
    clipboard = clipboard.splitlines()[-1]
    # show
    print(clipboard)

On the other hand there can be a way to access called operators from this list. But actually I don’t know how to retrieve the reports (if actually are stored in there).

>>> bpy.context.window_manager.operators[-1].name
'Merge by Distance'

1 Like

I found python info there https://stackoverflow.com/questions/16571150/how-to-capture-stdout-output-from-a-python-function-call

I run remove doubles twice to show that you can run several operators in a context manager
or you can have one context manager by operator…

import bpy
from io import StringIO 
import sys

class Capturing(list):
    def __enter__(self):
        self._stdout = sys.stdout
        sys.stdout = self._stringio = StringIO()
        return self
    def __exit__(self, *args):
        self.extend(self._stringio.getvalue().splitlines())
        del self._stringio    # free up some memory
        sys.stdout = self._stdout

def main(self, context):
    with Capturing() as output:
        bpy.ops.mesh.remove_doubles()
        bpy.ops.mesh.remove_doubles()
    print("output", output)
    self.report({'INFO'}, output[0])

class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"
    bl_options = {'REGISTER', 'UNDO'}
    

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

    def execute(self, context):
        main(self,context)
        return {'FINISHED'}


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

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

if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.simple_operator()

by the way you should change the title to: from an operator inside another operator