Как исправить ошибку UnicodeDecodeError: кодек ‘utf-32-le’ не может декодировать байты в позиции 16-19 при попытке запустить функцию python3 в node-red

#python #json #python-3.x #node-red

#python #json #python-3.x #узел-красный

Вопрос:

Я пытаюсь запустить пустую функцию python3 (только return msg в ней) в node-red с узлом ‘node-red-contrib-python3-function’, но я получаю ошибку, указанную в названии. У меня установлен Python 3.7.3 atm. Полученное сообщение об ошибке (повторяется 10 раз):

 10 Apr 13:55:38 - [info] [python3-function:TEST] Python function 'TEST' running on PID 4616
10 Apr 13:55:40 - [info] [python3-function:TEST] Raw message received: b'x01x00x00x00x00x00x00x00?x00x00x00x00x00x00x00{"topic":"","payload":1554897340119,"_msgid":"c6460d66.0d218"}n'

10 Apr 13:55:40 - [error] [python3-function:TEST] Traceback (most recent call last):
  File "<string>", line 72, in <module>
  File "C:Python37libjson__init__.py", line 343, in loads
    s = s.decode(detect_encoding(s), 'surrogatepass')
  File "C:Python37libencodingsutf_32_le.py", line 11, in decode
    return codecs.utf_32_le_decode(input, errors, True)
UnicodeDecodeError: 'utf-32-le' codec can't decode bytes in position 16-19: code point not in range(0x110000)

10 Apr 13:55:40 - [error] [python3-function:TEST] Python Function process exited with code 1
10 Apr 13:55:40 - [info] [python3-function:TEST] Python function 'TEST' running on PID 8640
10 Apr 13:55:42 - [info] [python3-function:TEST] Raw message received: b'x01x00x00x00x00x00x00x00@x00x00x00x00x00x00x00{"topic":"","payload":1554897342120,"_msgid":"d57b8b5f.5ef468"}n'

10 Apr 13:55:42 - [error] [python3-function:TEST] Traceback (most recent call last):
  File "<string>", line 72, in <module>
  File "C:Python37libjson__init__.py", line 343, in loads
    s = s.decode(detect_encoding(s), 'surrogatepass')
  File "C:Python37libencodingsutf_32_le.py", line 11, in decode
    return codecs.utf_32_le_decode(input, errors, True)
UnicodeDecodeError: 'utf-32-le' codec can't decode bytes in position 16-19: code point not in range(0x110000)

10 Apr 13:55:42 - [error] [python3-function:TEST] Python Function process exited with code 1
  

Следующий код выполняется узлом (находится в python3-function.js в этой папке node modules lib) при развертывании потока я сам добавил печать необработанного сообщения.

 def python_function(msg):
`   indentLines(config.func, 4)  
                `
while True:
    raw_msg = channel.readline()
    print(f"Raw message received: {raw_msg}")
    if not raw_msg:
        raise RuntimeError('Received EOF!')
    msg = json.loads(raw_msg)
    msgid = msg["_msgid"]
    node = Node(msgid, channel)
    res_msgs = python_function(msg)
    node.send(res_msgs)
`
  

Где канал:

 channel = None
if sys.version_info[0]<3:
    channel = os.fdopen(3, "r ")
else:
    channel = os.fdopen(3, "rb", buffering=0)
  

Узел определяется как:

 class Node(object):
    def __init__(self, msgid, channel):
        self.__msgid = msgid
        self.__channel = channel

    def send(self, msg):
        msg = Msg(Msg.SEND, msg, self.__msgid)
        self.send_to_node(msg)

    def log(self, *args):
        msg = Msg(Msg.LOG, args, self.__msgid)
        self.send_to_node(msg)

    def warn(self, *args):
        msg = Msg(Msg.WARN, args, self.__msgid)
        self.send_to_node(msg)

    def error(self, *args):
        msg = Msg(Msg.ERROR, args, self.__msgid)
        self.send_to_node(msg)

    def status(self, *args):
        msg = Msg(Msg.STATUS, args, self.__msgid)
        self.send_to_node(msg)

    def send_to_node(self, msg):
        m = msg.dumps()
        if sys.version_info[0]>2:
            m = m.encode("utf-8")
        self.__channel.write(m)
  

Комментарии:

1. Ваша проблема здесь в том, что возвращаемый объект channel.readline() не является чистым JSON. Впереди есть пара байтов, которые нельзя преобразовать обратно в кодировку utf-32. Так что посмотрите, кто отправляет сообщение на канал

2. Я не могу изменить все, что отправляется на этот канал. Я понятия не имею, как node-red работает таким образом. Я думаю, лучше всего было бы попытаться просто удалить байты перед ‘{‘, если это возможно.