JSR223 Python and unicode

Hello to all,

I am using the jython helpers library with the jython-standalone-2.7.2.jar and I trying to use a simplified util.py example from @rlkoshak in Journey to JSR223 Python 1 of 9

from core.jsr223 import scope
from core.actions import NotificationAction
from configuration import admin_email

def send_info(message, logger):
    logger.info("[INFO ALERT] {}".format(message))

but when calling send_info in my test rule file specifying that the string has unicode with u"string":

from core.rules import rule
from core.triggers import when
import personal.util
from personal.util import send_info

@rule("JythonInfoTest", description="Jython Info Test", tags=["info"])
@when("Item SwitchJythonInfoTest changed")
def jython_info_test_rule(event):
    if items.SwitchJythonInfoTest == ON:
        send_info(u"Máquina Lavar Roupa - Começou!", jython_info_test_rule.log)
        send_info(u"Máquina Lavar Roupa - Terminou!", jython_info_test_rule.log)

I have an error:

2020-07-31 10:01:11.090 [ERROR] [jsr223.jython.JythonInfoTest        ] - Traceback (most recent call last):
  File "/etc/openhab2/automation/lib/python/core/log.py", line 51, in wrapper
    return fn(*args, **kwargs)
  File "<script>", line 25, in jython_info_test_rule
  File "/etc/openhab2/automation/lib/python/personal/util.py", line 6, in send_info
    out = str(message)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1' in position 1: ordinal not in range(128)

2020-07-31 10:01:11.101 [ERROR] [e.automation.internal.RuleEngineImpl] - Failed to execute rule '458332f8-34da-4007-9ec7-9d1921b7a08e': Fail to execute action: 1

If I call it like this it works:

jython_test_rule.log.info(u"Máquina Lavar Roupa - Começou!")
jython_test_rule.log.info(u"Máquina Lavar Roupa - Terminou!")

but using the library function send_info it does not. I know this should be something simple for you guys but I did not manage to get it working.

Could you please give me hand on this one.

Thanks for your help.

You’ll need to also use unicode in your module…

def send_info(message, logger):
    logger.info(u"[INFO ALERT] {}".format(message))

You also do not need any of those imports in your module.

I’m curious though… why not just use the log attribute that’s added to the rule’s callback function?

@rule("JythonInfoTest", description="Jython Info Test", tags=["info"])
@when("Item SwitchJythonInfoTest changed")
def jython_info_test_rule(event):
    if items.SwitchJythonInfoTest == ON:
        jython_info_test_rule.log.info(u"Máquina Lavar Roupa - Começou!")
        jython_info_test_rule.log.info(u"Máquina Lavar Roupa - Terminou!")

Regarding this, you are absolutely right but I have also notifications in the module like the example and decided to use the whole example. But you are right it complicates more then it helps…

I did not remember to test this :frowning:, thanks for the input.
After the test the string is still not formatted correctly:

2020-07-31 10:38:36.716 [INFO ] [jsr223.jython.JythonInfoTest        ] - [INFO ALERT] SwitchJythonInfoTest ON
2020-07-31 10:38:36.719 [INFO ] [jsr223.jython.JythonInfoTest        ] - [INFO ALERT] Máquina Lavar Roupa - Começou!
2020-07-31 10:38:38.527 [INFO ] [jsr223.jython.JythonInfoTest        ] - [INFO ALERT] SwitchJythonInfoTest OFF
2020-07-31 10:38:38.529 [INFO ] [jsr223.jython.JythonInfoTest        ] - [INFO ALERT] Máquina Lavar Roupa - Terminou!


Does you script look the same as in the first post? You need to use unicode strings everywhere you are using unicode.

Passing a logger as an argument is a bad idea for several reasons. A big one being that you do not know the source of the logs. If you need to log in your module, just create a logger for use in the module…

from core.log import logging, LOG_PREFIX
LOG = logging.getLogger("{}.personal.utils".format(LOG_PREFIX))

Thanks for your answer. You are right, I just added a line print the status of the test switch that fires the rule.

Thanks for the explanation, understood. I am going to change this then.