LINUX.ORG.RU

Python падает при попытке декодировать строку \x1b\xe2\x80

 


0

4

Пытаюсь сделать оброботчик tty. Вроде бы ничего сложного, но при поптыке вызвать метод decode() в строке где есть последовательность «\x1b\xe2\x80\xa6P» питон просто отваливается. Не кидает исключения - ничего - просто молча падает. По идее опция errors=‘ignore’ должна помочь, но не помогает.

out = b'Mounting \x1b[0;1;39mdev-mqueue.mount\x1b\xe2\x80\xa6POSIX Message Queue File System...\r\r\n['
print ("decode start")
print (out.decode(errors='ignore'))
print ("decode end")

Версия Python 3.10.12

PS: Валиться только при запуске из под tmux. Если запустить в gnome-terminal, то без опции errors=‘ignore’, ругается на символ \xe2.



Последнее исправление: guskov_roman (всего исправлений: 1)
╰─$ cat test.py
out = b'Mounting \x1b[0;1;39mdev-mqueue.mount\x1b\xe2\x80\xa6POSIX Message Queue File System...\r\r\n['
print ("decode start")
print (out.decode(errors='ignore'))
print ("decode end")

╰─$ python test.py
decode start
Mounting dev-mqueue.mount��POSIX Message Queue File System...
[
decode end
╰─$
FishHook
()
Последнее исправление: FishHook (всего исправлений: 1)
Ответ на: комментарий от AntonI

Там 4 строчки кода, чего там можно не заметить то. Вот именно этот код и падает.

Причем отладчик тоже намертво зависает на это функции:

-> print(out.decode(‘latin-1’, errors=‘replace’)) (Pdb) n Mounting dev-mqueue.mount

guskov_roman
() автор топика
Последнее исправление: guskov_roman (всего исправлений: 1)
Ответ на: комментарий от FishHook

можно заменить на просто print (out.decode(errors=‘ignore’)) результат будет такой же. Новый симптом: валиться только при запуске из под tmux. Если просто запустить в gnome-terminal, то работает

guskov_roman
() автор топика
Ответ на: комментарий от FishHook

Ему почему то не нравится код \x1b. Если убрать этот символ, то и в tmux работает.

out = b'Mounting \x1b[0;1;39mdev-mqueue.mount\x1b\xe2\x80\xa6POSIX Message Queue File System...\r\r\n['

out = out.replace(b'\x1b', b'')
print ("decode start")
print(out.decode())  
print ("decode end")
guskov_roman
() автор топика
Последнее исправление: guskov_roman (всего исправлений: 1)
Ответ на: комментарий от guskov_roman

Это не питону не нравится, это терминалу не нравится. Смотри, запишим эту строку в файл:

python -c "f=open('test.out', 'bw'); f.write(b'Mounting \x1b[0;1;39mdev-mqueue.mount\x1b\xe2\x80\xa6POSIX Message Queue File System...\r\r\n[')

теперь, если сделать этому файлу cat, то получаем то же самое поведение, что и принт питоном. Если выйти из тмукса, то cat читает файл без проблем

FishHook
()
Последнее исправление: FishHook (всего исправлений: 1)
Ответ на: комментарий от unDEFER

\x1b – это Escape и с него начинаются все Escape-последовательности и от них можно всяких чудес в терминале ожидать.

Согласен, но это не я. Это вывод загрузки Linux - это он такое в терминал шлет. Непонятно только, почему tmux так реагирует и как это можно грамотно обойти

guskov_roman
() автор топика
Ответ на: комментарий от FishHook

Это решает проблему зависания, но ломает весь вывод. Смысл decode() тогда теряется. Проще вообще не сразу весь bytearray отправлять на вывод.

Вот такой будет вывод после out.translate(None, bytes(range(1, 32)))

Directories.[[0;32m  OK  [0m] Reached target [0;1;39mtimers.target[0m - Timer Units.[[0;32m  OK  [0m] Listening on [0;1;39mavahi-daemon.…NS/DNS-SD Stack Activation Socket.[[0;32m  OK  [0m] Listening on [0;1;39mdbus.socket[…- D-Bus System Message Bus Socket.[[0;32m  OK  [0m] Reached target [0;1;39msockets.target[0m - Socket Units.[[0;32m  OK  [0m] Reached target [0;1;39mbasic.target[0m - Basic System.         Starting [0;1;39maccounts-daemon.service[0m - Accounts Service...         Starting [0;1;39mavahi-daemon.serv…e[0m - Avahi mDNS/DNS-SD Stack...[[0;32m  OK  [0m] Started [0;1;39mcron.se[   16.392987] dwmac1000: Master AXI performs fixed burst lengthrvice[0m -…kg[   16.399700] 

А я хочу видеть красивый вывод:

[   14.275287] systemd[1]: Reached target slices.target - Slice Units.
[  OK  ] Reached target slices.target - Slice Units.
[   14.290335] systemd[1]: Reached target veritysetup.target - Local Verity Protected Volumes.
[  OK  ] Reached target veritysetup… - Local Verity Protected Volumes.
[   14.308621] systemd[1]: Listening on systemd-fsckd.socket - fsck to fsckd communication Socket.
[  OK  ] Listening on systemd-fsckd…sck to fsckd communication Socket.
[   14.327417] systemd[1]: Listening on systemd-initctl.socket - initctl Compatibility Named Pipe.
[  OK  ] Listening on systemd-initc… initctl Compatibility Named Pipe.
[   14.346845] systemd[1]: Listening on systemd-journald-audit.socket - Journal Audit Socket.
[  OK  ] Listening on systemd-journ…socket - Journal Audit Socket.

guskov_roman
() автор топика

\x1b\xe2\x80\xa6 выглядит как некорректная Escape последовательность. Потому что выходит за пределы ASCII-кодов.

И python там на самом деле никуда не отваливается. Это вывод перестаëт печататься. Вы можете добавить ещё одну Escape-последовательность для сброса сего странного состояния и тогда заработает.

unDEFER ★★★★★
()
Последнее исправление: unDEFER (всего исправлений: 1)

Проблема не в питоне, а в терминале. Дело в том что в некоторых терминалах, например, ESC и CTRL+[ могут иметь одинаковую последовательность символов, также и TAB с CTRL+I.

Похоже что в вашем случае, из-за поведения описанного выше, часть строки преобразуется в неверную escape последовательность при попытке декодирования которой питон не падает, а выполняет ее завершая работу. Следующие версии питона скорее всего имеют встроенное дополнительное экранирование таких последовательностей в декодере, потому они не выполняют ее и продолжают работу.

Вот почему tmux это делает

Вообще, покопайтесь вот тут, там несколько вариантов решения.

Obezyan
()
Последнее исправление: Obezyan (всего исправлений: 1)
Ответ на: комментарий от Obezyan

совет и итог +много

посылка если(нечто скорлированное с->)(у терминала: ) ESC==CTRL+[ и/или TAB==CTRL+I

это из ложного фсё

ибо ctrl(^) эт «просто» &1F(в тех случаях когда ==)

+много за виденье причины в излишнем разименновании(недоэкранированности)

qulinxao3 ★★
()
Последнее исправление: qulinxao3 (всего исправлений: 2)
Ответ на: комментарий от qulinxao3

совет и итог +много посылка если(нечто скорлированное с->)(у терминала: ) ESC==CTRL+[ >и/или TAB==CTRL+I это из ложного фсё ибо ctrl(^) эт «просто» &1F(в тех случаях когда ==) +много за виденье причины в излишнем >разименновании(недоэкранированности)

Ничего не понял

guskov_roman
() автор топика
Ответ на: комментарий от Obezyan

Вообще, покопайтесь вот тут, там несколько вариантов решения.

Это к сожалению не годится. Там речь идет про настройку tmux, а надо сделать так, что бы моя tty обертка работала независимо от того, где она запущена - просто в терминале или еще где.

Пока самое простое и рабочее решение - просто заменять \x1b на b''. Это не ломает вывод, но это конечно костыль

guskov_roman
() автор топика
Ответ на: комментарий от unDEFER

И python там на самом деле никуда не отваливается

Питон к сожалению тоже отваливается. Но не сразу. Да это и не важно на самом деле. Главное что он перестает выводить данные

guskov_roman
() автор топика
Ответ на: комментарий от guskov_roman

хм цветной вывод и достигается выдачей ansi кодов через esc- последовательности - поэтому «современные» консольные утилиты с скрасивостями - проверяют куда стримится их вывод если @real-tty@ то с ansi если «чисто поток» то ... иначе ещё как

крч см как это деляют обычные утилиты которые в файл пихают чиста текст а вывод подерживают с --colour опцией

просто рубить \x1b это оставлять в выходе муссор от самих команд форматирования ansi

qulinxao3 ★★
()
Ответ на: комментарий от qulinxao3

крч см как это деляют обычные утилиты которые в файл пихают чиста текст а вывод подерживают с –colour опцией

это например каких ?

просто рубить \x1b это оставлять в выходе муссор от самих команд форматирования ansi

Ну в принципе да. Как костыль можно выпиливать некорректную последовательность \x1b\xe2\x80\xa6, благо она там одна такая на весь вывод.

Ну а по хорошему надо сделать проверку на корректность Escape sequences и выпиливать левые.

guskov_roman
() автор топика
Ответ на: комментарий от guskov_roman

«похорошему» pipe получения открыть так что бы утилита генерирования данных выдавала бы plain utf8 без ansi-форматирования

если же генерация прибита гвоздями - найти какой фильтр который культурно ... и не морочится

qulinxao3 ★★
()
Ответ на: комментарий от qulinxao3

«похорошему» pipe получения открыть так что бы утилита генерирования данных выдавала бы plain utf8 без ansi-форматирования

Там нет никакой утилиты для генерирования данных. Это вывод с tty с другой железки на которой грузится linux. Собственно говоря это просто обертка на pyserial. Я получаю весь вывод в виде bytes начиная от предзагрузчика и заканчивая linux. При конвертации его в string и происходит данная ошибка.

guskov_roman
() автор топика

хм, а вот что интересного есть

     xterm-keys [on | off]
             If this option is set, tmux will generate xterm(1) -style function key sequences;
             these have a number included to indicate modifiers such as Shift, Alt or Ctrl
Morin ★★★★★
()
Ответ на: комментарий от pasquale

Притом, что systemd неправильно вставлял многоточия в свой вывод до версии 255.

Это ни на что не влияет Ну я не могу сказать, извините у вас systemd не той версии. А в новой версии еще что нибудь сломают. Надо что бы работало независимо от версии systemd или чего было то еще

guskov_roman
() автор топика
In [1]: out = b'Mounting \x1b[0;1;39mdev-mqueue.mount\x1b\xe2\x80\xa6POSIX Message Queue File System...\r\r\n['

In [2]: out.decode(encoding="utf8")
Out[2]: 'Mounting \x1b[0;1;39mdev-mqueue.mount\x1b…POSIX Message Queue File System...\r\r\n['

In [3]: print(out.decode(encoding="utf8"))
Mounting dev-mqueue.mountPOSIX Message Queue File System...
[

thunar ★★★★★
()