2
$\begingroup$

I am looking for a way to alter the default python environment generated by the text editor or the console. I want to add commonly used modules so that I don't have to import them every time. This doesn't seem to be possible with an add-on, as described here:

https://docs.blender.org/manual/en/latest/advanced/scripting/addon_tutorial.html

or a startup script, as described here:

https://docs.blender.org/api/current/info_overview.html

but maybe I am doing something wrong.

Background: in Maya, there's a user script which is executed (not imported) at startup. If you import modules in that script, they're available from the root namespace via the text editor and console.

I am looking for similar function, due to the text editor content not being independent of the scene, and getting wiped on each new scene or session. Relevant commands need to be either retyped, saved as part of the "startup file", or pasted from some external file every single time. None of these are workable.

Working from an external editor in this context is problematic, as well. When prototyping and learning, I interact directly with the session, incrementally and piecemeal, but in more than single line increments as are available in the console. This would be difficult or impossible to do fluidly with an external editor, at least in the same way as it works in maya.

$\endgroup$
1
  • $\begingroup$ I just assign stuff to bpy for debugging, since the same module's accessible from most places. $\endgroup$
    – Will Chen
    May 23, 2021 at 23:09

1 Answer 1

6
$\begingroup$

Look at the source code.

As with most spaces in the blender UI the code is available. In the case of the python console the UI in bl_ui/space_console.py and the nuts and bolts of the python console in scripts/modules/console_python.py

A code snippet from which, where the convenience imports and variables are added.

    namespace["__builtins__"] = sys.modules["builtins"]
    namespace["bpy"] = bpy

    # weak! - but highly convenient
    namespace["C"] = bpy.context
    namespace["D"] = bpy.data

    replace_help(namespace)

    console = InteractiveConsole(locals=namespace,
                                 filename="<blender_console>")

    console.push("from mathutils import *")
    console.push("from math import *")

An option (but a bad slippery-slope don't do it option) is to edit this to suit, however

a lesser evil could be to copy, rename and put in our user scripts/modules folder.

>>> bpy.utils.script_path_user()
'/home/batfinger/.config/blender/2.91/scripts'

For example sake have called it console_batpython.py

Purpose of the languages selector in the Python Console

enter image description here

and have one or a number of different options available via the menu. Which does involve having to select the language (... in this case python with different imports...) at least once per console

Add locals to a console.

Will find a number of run script in console addons, a couple of rippers that come to mind are by @CodemanX and @pinkvertex (the links escape me atm).

The main gist is using the module in conjunction with code as displayed in the script stub template. To run a script from the text editor and have it print to and available to inspect in the console.

Here is a script which when run adds locals to consoles in same screen.

import bpy
import bmesh
import console_python

for area in bpy.context.screen.areas:
    if area.type == 'CONSOLE':
        region = area.regions[-1]
        id = hash(region)
        con, stdout, stderr = console_python.get_console(id)
        # add to locals
        con.locals['bmesh'] = bmesh
        # update with locals from this script
        con.locals.update(locals())
        # push in some locals
        con.push("import itertools")
        con.push("foo = 3")

and in any console on the same screen as the text editor.

>>> itertools
<module 'itertools' (built-in)>

>>> bmesh
<module 'bmesh' (built-in)>

>>> foo
3

Text Editor

The concept of the text editor is to import all requirements as if it were any other module on disk. We can however write an operator based on the Text Editor > Templates > Python > External Script Stub

exec(compile(file.read(), filepath, 'exec'), global_namespace)

and replace file.read() with text_block.as_string() and add other members to global_namespace dictionary.

$\endgroup$

You must log in to answer this question.

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