Python: неожиданный результат при чтении байта 0xe0 - PullRequest
0 голосов
/ 18 февраля 2019
import msvcrt
while True:
    try:
        a=msvcrt.getch()
        a=a.decode('utf-8')
        print(a)
    except:
        print(a)

Приведенный выше фрагмент кода дает неожиданные результаты, когда я ввожу клавиши со стрелками или страницу вверх / страницу вниз / удаление и т. Д.

The output is as follows:
[I/P=a]
a #expected result
[I/P=UP ARROW]
b'\xe0'
H  #unexpected result

Я понимаю, что b '\ xe0' печатается, нопочему H печатается вместе с ним?H не печатается, когда я делаю это:

import msvcrt
a=msvcrt.getch()
print(a)#b'\xe0'
a=a.decode('utf-8')
print(a)
When I input UP ARROW here, it raises a UNICODEDECODERROR.

Я смотрел на другой вопрос, который объясняет, как работает msvcrt.getch (), но все равно не объясняет, почему я получаю два символа в первомкусок кода и только один символ во втором куске кода. Вместо ожидания ввода следующего символа, почему предполагается, что значение b'H '?

1 Ответ

0 голосов
/ 18 февраля 2019

Клавиши со стрелками (и функциональные клавиши и другие) требуют двух отдельных вызовов до msvcrt.getch.Когда вы нажимаете , первый возвращает b'\xe0', а второй возвращает b\x48. Ни один из них не является UTF-8 или даже ASCII.Первый из них не является допустимой последовательностью UTF-8, поэтому ваш вызов decode('utf-8') вызывает исключение.Второе значение представляет собой байтовое значение, представляющее ключевой код 72, который по совпадению оказывается тем же байтовым значением, которое представляет букву 'H' в UTF-8 или ASCII.

Из документации msvcrt (выделено мной):

msvcrt.getch()

Считать нажатие клавиши и вернуть полученный символ в виде байтастрока.Ничто не отражается на консоли.Этот вызов блокируется, если нажатие клавиши еще не доступно, но не будет ждать нажатия клавиши Enter.Если нажатая клавиша была специальной функциональной клавишей, она вернет '\000' или '\xe0'; следующий вызов вернет код ключа .Нажатие клавиши Control-C не может быть прочитано с помощью этой функции.

Вы можете увидеть проходящие байты с помощью такой программы:

import msvcrt

NEXT_CHARACTER_IS_KEYCODE = [b'0xe0', b'0x00']

while True:
  ch1 = msvcrt.getch()
  print("Main getch(): {}".format(ch1))
  if ch1 in NEXT_CHARACTER_IS_KEYCODE:
      ch2 = msvcrt.getch()
      print("  keycode getch(): {}".format(ch2))

Обратите внимание, что нет .decode('utf-8') там, поскольку getch не возвращает байты UTF-8 в любом случае.

(примечание: убедитесь, что вы действительно хотите использовать msvcrt.getch, поскольку это довольно необычный выбор, особенно в 2019 году.)

Связанный:

...