Ведение журнала Python застряло на определенном байте — 0x90

Я столкнулся с очень странной проблемой и, честно говоря, понятия не имею, что с этим делать, поэтому решил поспрашивать. Короче говоря, когда я пытаюсь записать байт 0x90 в свой logging.Logger, весь терминал Python зависает. Из всех байтов, которые я пробовал (все ASCII и множество других), это единственный, который показывает такое поведение. Подробности смотрите ниже.

Немного контекста

У меня есть приложение WX, которое получает данные из последовательного порта, отображает их и регистрирует. Прием данных из порта обрабатывается серверной частью, которую я всесторонне протестировал с помощью модульных тестов. Я совершенно уверен, что это работает как при использовании «изогнутой трубы» для отправки/получения байтов, так и при использовании Arduino для отправки байтов в приложение. Внешний интерфейс = приложение WX, похоже, тоже работает, т.е. отображает полученные байты и регистрирует их в logging.Logger.

Конкретная проблема

Я попытался повторить все мои модульные бэкэнд-тесты как тест черного ящика всего приложения. Все работает отлично, кроме одного случая, который отправляет несколько байтов, в том числе 0x90 = 58256 = 'ã'. К моему удивлению, как только этот байт получен, logging.Logger перестает отображать дальнейшие сообщения. Приложение, однако, продолжает работать вполне счастливо.

Что я пробовал и результаты

Этот бедный парень кажется, возникла проблема с тем же байтом, но ответов нет. У них была аналогичная проблема здесь, но не упоминайте никаких подробностей. В общем, в 0x90 нет ничего особенного, не так ли?

Я сузил свою проблему только до средства ведения журнала, см. MWE ниже. Если я просто запускаю MWE с терминала, он завершается без проблем. То же самое, если я запускаю его из интерпретатора Python или IPython в Anaconda. Результат:

.../tests$ python3 ./mwe.py 
0.5.1.2
(3, 5, 4)
2020-01-19 20:15:49,184 - MyLog - INFO - j
2020-01-19 20:15:49,184 - MyLog - INFO - 

Однако, если я открою интерпретатор Python, а затем построчно выполню MWE, он в конечном итоге зависнет, как только я попытаюсь записать 0x90. Кажется, нет никакого способа разблокировать терминал, даже с помощью Ctrl + C. Мне просто нужно убить процесс интерпретатора.

Есть идеи, что происходит? Большое спасибо, что посмотрели это.

MWE

import logging, sys
print(logging.__version__)
# 0.5.1.2
print(sys.version_info[:3])
# (3, 5, 4)
logger = logging.getLogger("MyLog")
handler = logging.StreamHandler()
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
handler.setLevel(logging.INFO)
logger.addHandler(handler)
logger.info(chr(0x6a))
# 2020-01-18 20:39:00,696 - MyLog - INFO - j
logger.info(chr(0x90))
# 2020-01-18 20:39:07,617 - MyLog - INFO -
# Python console is stalled from now-on.

Решение

Элегантное решение проблемы, которая заключается в очистке строки от управляющих символов, находится в этот пост.


person Aleksander Lidtke    schedule 19.01.2020    source источник
comment
Обратите внимание, что это не связано с ведением журнала. Попробуйте запустить интерактивный сеанс Python, и print(chr(0x90)) также уничтожит ваш терминал.   -  person blues    schedule 20.01.2020


Ответы (1)


Это происходит потому, что консоль Python неправильно воспринимает это как специальный управляющий символ для терминала. В частности, он запускает строку управления устройством. Их необходимо завершить, иначе терминал вешать. Для проверки попробуйте выполнить print(chr(0x90)) или print(chr(0x90)+chr(0x9C)) в консоли Python. Второй ничего не сделает, так как у него есть завершающий байт 0x9c, а первый его повесит.

person blues    schedule 20.01.2020
comment
Большое спасибо @blues! Никогда не думал об этом. Как вы думаете, чтобы сделать мое приложение отказоустойчивым, мне следует следить за всеми этими управляющими строками и каким-то образом следить за тем, чтобы я обрабатывал их отдельно? Есть ли встроенный в Python список управляющих строк? - person Aleksander Lidtke; 20.01.2020