5
$\begingroup$

I'm trying to print to the console in Blender using the following function. However, it does not work if the console is not in view (i.e. it's not part of area in screen.areas). How can the console be targeted if it's out of view?

def bprint(*objects, sep=" ", end="\n"):
    """
    Print to Blender's console
    """
    output = ""
    for obj in objects:
        output += str(obj) + sep
    output += end

    for window in bpy.context.window_manager.windows:
        screen = window.screen
        for area in screen.areas:
            if area.type == "CONSOLE":
                override = {"window": window, "screen": screen, "area": area}
                bpy.ops.console.scrollback_append(
                    override, text=str(output), type="OUTPUT"
                )
$\endgroup$

1 Answer 1

5
$\begingroup$

Instead of iterating over areas of current screen, you need to iterate over areas of all workspaces. However, one workspace can be instanced multiple times (screens), but it conveniently lists them for you to iterate over. However, you also need to know which window the screen belongs to, and I think, as long as you don't use a very buggy feature Window -> New Main Window (for me, when I have two such windows and switch workspaces, they duplicate in place, and soon just crash Blender), all windows but the main one will have just one screen. Though you could run the script from non-main window, so maybe you should also set the "window": bpy.context.window_manager.windows[0] override when you don't find a window's active screen to be one of the console screens. Either way I expect this script to be outdated as soon as the mentioned bug(s) with "New Main Window" are fixed, but maybe not, maybe only active tab makes the screen used by the window? I could test it, maybe later...

import bpy

def bprint(*args, sep=" ", end="\n"):
    """
    Print to Blender's consoles in all workspaces
    """
    from io import StringIO
    buffer = StringIO()
    print(*args, sep=sep, end=end, file=buffer)
    output = buffer.getvalue()
    
    overrides = [
        {'screen': screen, 'area': area}
        for workspace in bpy.data.workspaces
        for screen in workspace.screens
        for area in screen.areas
        if area.type == 'CONSOLE'
    ]
    for override in overrides:
        for window in bpy.context.window_manager.windows:
            if window.screen == override['screen']:
                override['window'] = window
        with bpy.context.temp_override(**override):
            bpy.ops.console.scrollback_append(text=output, type="OUTPUT")
                
                
bprint("Testing", 2, object())

Oh I changed the context override to the new method, but you surely know how to convert it back to the old one if needed.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .