Is there is a way to use this newer binding while creating importable python modules? I wanted to port over my previous work from the Jython bindings to this binding to get my home automation functional again. As far as I can tell, however, the new binding just recursively loads every .py file it sees, which is unfriendly to modules.
This did help it load as a module correctly. Unfortunately, relative module imports are non-functional for me. I have to fully qualify all module imports even for other files in the same module.
for me this works. I tested it with openhab 5.0.3 and the latest marketplace version of this addon. Additionally I tested it with openhab 5.1 snapshot (upcoming milestone3)
Here is my scenario
conf/automation/python/test.py
from test import TEST_VAR1
print(TEST_VAR1)
conf/automation/python/lib/test/__init__.py
from .subtest import TEST_VAR2
TEST_VAR1 = TEST_VAR2
Oh interesting. That works for me as well, but the relative module imports I was using were broken.
If I do
from itemmanager import add_item
it doesn’t work. It complains it can’t find itemmanager despite being a direct submodule.
If I do
from .itemmanager import add_item
it works perfectly fine. My existing python code all used the former form. There might be something funky going on with the module loader, I wouldn’t expect any behavior difference from the above, they should be semantically equivalent.
Not a big deal, I already switched my module imports to absolute, but I think there might be a bug hiding there.
[b.automation.pythonscripting.home.py] - File “/openhab/conf/automation/python/lib/mmdev/manager.py”, line 6, in from itemmanager import add_item
2025-11-20 11:01:22.859 [ERROR] [b.automation.pythonscripting.home.py] - ModuleNotFoundError, No module named ‘itemmanager’
I guess it is related to python3 in graalpy vs python2 in jython. Python 3 is more strict with imports and requires the dot notation with relative imports. In addition to one dot, you can also use two dots to access the parent module.
Yeah, I think you are correct, sorry for that. I write python3 code all the time, but looking through the older Jython stuff I’ve written for openhab put me into a funky headspace.
I’m excited to get this all on python3! Writing it all in python2 was rather annoying.
Hi. I am struggling to get this binding to work. I was using jython in 4.3.3. Now I can’t get this to work in either 5.0 and 5.1.
I am now running openhab 5.1.0~M2 on openSUSE Leap 15.6 installed from the official openhab.jfrog.io repository.
Here is what I get in openhab-cli console:
openhab> pythonscripting info
Python Scripting Environment:
======================================
Runtime:
Bundle version: 5.1.0.M2
GraalVM version: 24.2.1
Python version: 3.11.7
Helper lib version: 1.0.13
VEnv state: disabled
Type hints: available
Directories:
Scripts: /etc/openhab/automation/python
Libraries: /etc/openhab/automation/python/lib
Typing: /etc/openhab/automation/python/typings
Temp: /var/lib/openhab/tmp
VEnv: /var/lib/openhab/cache/org.openhab.automation.pythonscripting/venv
Python Scripting Add-on Configuration:
======================================
Python Environment
scopeEnabled: true
helperEnabled: true
injectionEnabled: 2
System Behavior
pipModules:
nativeModules: true
dependencyTrackingEnabled: true
cachingEnabled: true
jythonEmulation: false
openhab> pythonscripting update check
Latest version '1.0.13' already installed.
openhab> pythonscripting console
Loading Python script engine...[python::PythonContext] WARNING: could not determine Graal.Python's core path - you may need to pass --python.CoreHome.
[python::PythonContext] WARNING: could not determine Graal.Python's sys prefix path - you may need to pass --python.SysPrefix.
[python::PythonContext] WARNING: could not determine Graal.Python's standard library path. You need to pass --python.StdLibHome if you want to use the standard library.
[python::PythonContext] WARNING: could not determine Graal.Python's C API library path. You need to pass --python.CAPI if you want to use the C extension modules.
[python::PythonContext] WARNING: could not determine Graal.Python's C API library path. You need to pass --python.CAPI if you want to use the C extension modules.
[python::PythonContext] WARNING: could not determine Graal.Python's JNI library. You need to pass --python.JNILibrary if you want to run, for example, binary HPy extension modules.
[python::PythonContext] WARNING: could not determine Graal.Python's C API library path. You need to pass --python.CAPI if you want to use the C extension modules.
[python::PythonContext] WARNING: could not determine Graal.Python's C API library path. You need to pass --python.CAPI if you want to use the C extension modules.
[python::PythonContext] WARNING: could not determine Graal.Python's JNI library. You need to pass --python.JNILibrary if you want to run, for example, binary HPy extension modules.
Error: null in /etc/openhab/automation/python/lib/openhab/__wrapper__.py at line number 1 at column number 1
This is what appears in log whenever I try pythonscript console or when it tries to load any python script:
2025-11-24 16:15:09.256 [DEBUG] [cripting.internal.PythonScriptEngine] - Lock acquired before invocation for engine '<uninitialized>'
2025-11-24 16:15:09.256 [DEBUG] [cripting.internal.PythonScriptEngine] - Initializing GraalPython script engine 'python-console-6487106e-66bd-4abd-8c3a-7e30d34d1664' ...
2025-11-24 16:15:09.268 [ERROR] [cripting.internal.PythonScriptEngine] - Traceback (most recent call last):
2025-11-24 16:15:09.268 [ERROR] [cripting.internal.PythonScriptEngine] - File "/etc/openhab/automation/python/lib/openhab/__wrapper__.py", line 96, in <module>
2025-11-24 16:15:09.269 [ERROR] [cripting.internal.PythonScriptEngine] - __import_wrapper__()
2025-11-24 16:15:09.269 [ERROR] [cripting.internal.PythonScriptEngine] - File "/etc/openhab/automation/python/lib/openhab/__wrapper__.py", line 11, in __import_wrapper__
2025-11-24 16:15:09.269 [ERROR] [cripting.internal.PythonScriptEngine] - import traceback
2025-11-24 16:15:09.269 [ERROR] [cripting.internal.PythonScriptEngine] - ModuleNotFoundError: No module named 'traceback'
2025-11-24 16:15:09.270 [DEBUG] [cripting.internal.PythonScriptEngine] - Failed to execute script (PolyglotException) for engine 'python-console-6487106e-66bd-4abd-8c3a-7e30d34d1664': at org.graalvm.polyglot.Context.eval(Context.java:416)
at org.openhab.automation.pythonscripting.internal.PythonScriptEngine.beforeInvocation(PythonScriptEngine.java:319)
at org.openhab.automation.pythonscripting.internal.scriptengine.InvocationInterceptingPythonScriptEngine.eval(InvocationInterceptingPythonScriptEngine.java:43)
at java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:262)
at org.openhab.automation.pythonscripting.internal.console.PythonConsoleCommandExtension.lambda$0(PythonConsoleCommandExtension.java:195)
... 22 more
The system has python3.11 installed and the traceback module is there (not sure if that is relevant):
# python3.11
Python 3.11.13 (main, Jun 09 2025, 21:55:43) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import traceback
>>>
Do I need any additional dependencies installed on the system?
Following the Yum or Dnf Based Systems instructions I added the repository and installed openhab and openhab-addons packages. This worked well for me in the past. The issue happens to be with both 5.0 from the stable repository and 5.1 from the testing repository.
I believe the pythonscripting addon comes from a /usr/share/openhab/addons/openhab-addons-5.1.0.M2.kar file that is in the openhab-addons package.
Can you also show the startup logs. just to check if there are some additional errors.
Somehow, at one moment it was suddenly working, until I restarted openhab and it stopped again. I don’t know how it happened. I wonder if there is some timing / order of initialization issue.
I will try to reproduce with a VM running opensuse leap 15.6
But a first check showed me that homeassistent has the same problem.
2025-11-24 20:21:54.810 [WARN ] [t.internal.HomeAssistantPythonBridge] - could not determine Graal.Python's sys prefix path - you may need to pass --python.SysPrefix.
2025-11-24 20:21:54.810 [WARN ] [t.internal.HomeAssistantPythonBridge] - could not determine Graal.Python's standard library path. You need to pass --python.StdLibHome if you want to use the standard library.
2025-11-24 20:21:54.811 [WARN ] [t.internal.HomeAssistantPythonBridge] - could not determine Graal.Python's C API library path. You need to pass --python.CAPI if you want to use the C extension modules.
2025-11-24 20:21:55.092 [WARN ] [t.internal.HomeAssistantPythonBridge] - could not determine Graal.Python's C API library path. You need to pass --python.CAPI if you want to use the C extension modules.
2025-11-24 20:21:55.093 [WARN ] [t.internal.HomeAssistantPythonBridge] - could not determine Graal.Python's JNI library. You need to pass --python.JNILibrary if you want to run, for example, binary HPy extension modules.
2025-11-24 20:21:55.320 [INFO ] [e.automation.internal.RuleEngineImpl] - Rule engine started.
2025-11-24 20:21:56.358 [WARN ] [t.internal.HomeAssistantPythonBridge] - could not determine Graal.Python's C API library path. You need to pass --python.CAPI if you want to use the C extension modules.
2025-11-24 20:21:56.488 [WARN ] [t.internal.HomeAssistantPythonBridge] - could not determine Graal.Python's C API library path. You need to pass --python.CAPI if you want to use the C extension modules.
2025-11-24 20:21:56.488 [WARN ] [t.internal.HomeAssistantPythonBridge] - could not determine Graal.Python's JNI library. You need to pass --python.JNILibrary if you want to run, for example, binary HPy extension modules.
2025-11-24 20:21:57.984 [ERROR] [t.internal.HomeAssistantPythonBridge] - bundle org.openhab.binding.mqtt.homeassistant:5.1.0.M2 (317)[org.openhab.binding.mqtt.homeassistant.internal.HomeAssistantPythonBridge(483)] : Error during instantiation of the implementation object
This is a strong sign that something with your installation is wrong.
Thank you for going such lengths to try to reproduce it. I also tried to install it in fresh VM and it works. I’ll try to get the configuration in the VM to match my system’s configuration and see if it breaks at some point or if I can spot a difference…
I figured out what the problem was. This github comment gave me a hint that the .cache directory in the home directory of the openhab user is important for the pythonscripting plugin.
The openhab user on my system was created long time ago and had a non-existing directory set as its home. In contrast the new installation in VM had openhab user with the /var/lib/openhab directory set as its home. When I changed the home on my system, the pythonscripting started working again.
Is there any update regarding graalyp? I still think that having an individual VEnv for a specific rule and also setting it up via rule might be usefull.
I’ve had trouble locating any documentation or examples of using the cache in a 1:1 way like JS scripting, but I think I have figured out the main functions. What does the compute object do?
from scope import cache
cache.privateCache.put('private_key', 'value')
cache.sharedCache.put('shared_key', 'value')
val1 = cache.privateCache.get('private_key')
val2 = cache.sharedCache.get('shared_key')
cache.privateCache.remove('private_key')
cache.sharedCache.remove('shared_key')
#Not sure what these are for:
#cache.privateCache.compute
#cache.sharedCache.compute
/**
* Attempts to compute a mapping for the specified key and its current mapped value
* (or null if there is no current mapping).
*
* See {@code java.util.Map.compute()} for details.
*
* @param key the key of the requested value.
* @param remappingFunction the remapping function to compute a value.
* @return the new value associated with the specified key, or null if none
*/
The Java Map JavaDoc is:
/**
* Attempts to compute a mapping for the specified key and its current
* mapped value (or {@code null} if there is no current mapping). For
* example, to either create or append a {@code String} msg to a value
* mapping:
*
* <pre> {@code
* map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))}</pre>
* (Method {@link #merge merge()} is often simpler to use for such purposes.)
*
* <p>If the remapping function returns {@code null}, the mapping is removed
* (or remains absent if initially absent). If the remapping function
* itself throws an (unchecked) exception, the exception is rethrown, and
* the current mapping is left unchanged.
*
* <p>The remapping function should not modify this map during computation.
*
* @implSpec
* The default implementation is equivalent to performing the following
* steps for this {@code map}:
*
* <pre> {@code
* V oldValue = map.get(key);
* V newValue = remappingFunction.apply(key, oldValue);
* if (newValue != null) {
* map.put(key, newValue);
* } else if (oldValue != null || map.containsKey(key)) {
* map.remove(key);
* }
* return newValue;
* }</pre>
*
* <p>The default implementation makes no guarantees about detecting if the
* remapping function modifies this map during computation and, if
* appropriate, reporting an error. Non-concurrent implementations should
* override this method and, on a best-effort basis, throw a
* {@code ConcurrentModificationException} if it is detected that the
* remapping function modifies this map during computation. Concurrent
* implementations should override this method and, on a best-effort basis,
* throw an {@code IllegalStateException} if it is detected that the
* remapping function modifies this map during computation and as a result
* computation would never complete.
*
* <p>The default implementation makes no guarantees about synchronization
* or atomicity properties of this method. Any implementation providing
* atomicity guarantees must override this method and document its
* concurrency properties. In particular, all implementations of
* subinterface {@link java.util.concurrent.ConcurrentMap} must document
* whether the remapping function is applied once atomically only if the
* value is not present.
*
* @param key key with which the specified value is to be associated
* @param remappingFunction the remapping function to compute a value
* @return the new value associated with the specified key, or null if none
* @throws NullPointerException if the specified key is null and
* this map does not support null keys, or the
* remappingFunction is null
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
({@linkplain Collection##optional-restrictions optional})
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
* ({@linkplain Collection##optional-restrictions optional})
* @throws IllegalArgumentException if some property of the specified key
* or value prevents it from being stored in this map
* ({@linkplain Collection##optional-restrictions optional})
* @since 1.8
*/
Exactly how such an operation looks in Python I don’t know, but basically it lets you update the cached value using a function where the key and the old value are inputs.