modifying the default python environment 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 &quot;startup file&quot;, 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.
The console is a &quot;start-up&quot; script.

This doesn't seem to be possible with an add-on or a startup script,
but maybe I am doing something wrong.

Yes indeed, Maybe you are,... hard to tell, have some suggestions, won't go there.
Look at the source code.
Just 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[&quot;__builtins__&quot;] = sys.modules[&quot;builtins&quot;]
    namespace[&quot;bpy&quot;] = bpy

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

    replace_help(namespace)

    console = InteractiveConsole(locals=namespace,
                                 filename=&quot;&lt;blender_console&gt;&quot;)

    console.push(&quot;from mathutils import *&quot;)
    console.push(&quot;from math import *&quot;)

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.
&gt;&gt;&gt; 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

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(&quot;import itertools&quot;)
        con.push(&quot;foo = 3&quot;)

and in any console on the same screen as the text editor.
&gt;&gt;&gt; itertools
&lt;module 'itertools' (built-in)&gt;

&gt;&gt;&gt; bmesh
&lt;module 'bmesh' (built-in)&gt;

&gt;&gt;&gt; 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 &gt; Templates &gt; Python &gt; 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.