Modules and Imports
Split plugin code safely and use Elyx's isolated import system.
Modules and imports
Every installed plugin receives its own internal module namespace:
You do not normally type this name. It prevents two plugins with identically
named files from sharing entries in sys.modules.
Import local modules
Given:
main.py can use familiar imports:
The same imports in another plugin resolve to that other plugin's files.
Relative imports also work:
For nested entry points, relative imports are often clearer:
Dynamic imports
Use the public Elyx helper when a module name is computed at runtime:
If a matching local module exists, elyx.import_module loads it from the
calling plugin. Otherwise it falls back to Python's normal import system.
Do not rely on this for local modules:
A plain dynamic import has no plugin context and may bypass Elyx's local
resolution. Use elyx.import_module.
Packages and namespace directories
Both regular packages and directories without __init__.py are supported:
Adding __init__.py is still recommended because it makes the same source
tree work in desktop tooling and static analyzers.
Supported Python files
Elyx can load:
.pysource modules.pycbytecode modules- packages with
__init__.pyor__init__.pyc - namespace directories
Bytecode must match the Python runtime's magic number. This SDK uses Python 3.11, so compile release bytecode with Python 3.11.
Bytecode is version-specific
A .pyc built with another Python version is rejected as incompatible.
Bytecode is not a security boundary and does not protect secrets.
Import data files as modules
JSON, YAML, YML, and TXT files can be imported when their stem is a valid module path.
Given config.json:
Use:
For notice.txt:
Data modules are convenient for code-oriented configuration. Files which are
part of the user-facing resource set usually belong under assets instead.
Reserved and external top-level modules
The importer always leaves important SDK and Java roots to the normal runtime, including:
Do not create local packages with those names. Also avoid shadowing Python
standard-library names such as json, pathlib, or typing; local files
with those names make code hard to reason about.
Reload behavior
When Elyx reloads or unloads a plugin, it removes that plugin's namespaced modules and invalidates path caches. The next load executes fresh code.
This isolation covers Python modules. Process-global state outside the plugin namespace still needs explicit cleanup:
- Java hooks and menu items are cleaned up by the host
- threads, sockets, observers, and custom listeners created by your code must
be stopped in
on_plugin_unload - mutations to third-party modules remain global until the process restarts
Import only the public Elyx facade
Supported:
Engine, importer, installer, and plugin model modules are private. Do not discover or import them by physical file path; they can be renamed or reorganized without a deprecation period.