msvcrt.getch() каждый раз обнаруживает пробел

Я пишу простой код на Python, который должен обнаруживать мои нажатия клавиш, но по какой-то причине обнаруживает пробел после каждого нажатия клавиши.

Код:

import msvcrt

print("press 'escape' to quit...")
text=""
while 1:
    char = msvcrt.getch()
    print(ord(char))

Пример запуска:

Input: aaaaa

Output:
97
0
97
0
97
0
97
0
97
0

person Antonio Iorga    schedule 27.04.2018    source источник
comment
Так в чем проблема? какой у вас код печатается?   -  person ᴀʀᴍᴀɴ    schedule 27.04.2018


Ответы (1)


Это не обнаружение пространства. Пространство 32, а не 0.

Происходит то, что вы используете широкосимвольный терминал, но читаете его как байты, поэтому вы видите байты UTF-16-LE. В UTF-16-LE a — это два байта, 97 и 0. Если вы прочитаете их так, как будто это два символа ASCII вместо одного символа UTF-16-LE, вы получите a, за которым следует \0.

Обратите внимание, что вы получаете обратно не 'a\0a\0a\0', а b'a\0a\0a\0'. Таким образом, вы можете буферизовать их в bytes или bytearray и использовать для них decode('utf-16-le'). Но это противоречит цели чтения по одному символу за раз.

Самое простое решение — использовать getwch вместо getch. В основном это будет делать то, что вы хотите — возвращать односимвольное значение str, например 'a', а не два отдельных однобайтовых значения bytes.

Все еще могут быть некоторые проблемы с астральными символами (все, что выше U+FFFF), отображаемыми как два отдельных суррогата вместо одного символа, а «специальные ключи» по-прежнему будут отображаться как Unicode U+0000 или U+00E0, за которыми следует ключевой код (или, если вы иметь более старый Python, возможно, как сломанный U+E0xx с кодом клавиши, встроенным в символ). Но в остальном все будет работать так, как вы ожидали.

person abarnert    schedule 27.04.2018
comment
getch вызывает ReadConsoleInputA, который возвращает ввод с клавиатуры, закодированный в соответствии с текущей кодовой страницей ввода консоли, которая по умолчанию является OEM и не может быть установлена ​​в UTF-16LE (кодовая страница 1200). Либо есть ошибка в версии OP среды выполнения C, либо ошибка в самой консоли (чаще в Windows 10, поскольку MS активно обновляет код консоли), либо какая-то неправильно работающая библиотека или альтернативный терминал (например, ConEmu). подключил ReadConsoleInputA в текущем процессе. - person Eryk Sun; 28.04.2018
comment
@eryksun ConEmu может быть возможным, но я, честно говоря, понятия не имею, как провести его через диагностику того, как он испортил свою консоль. И я думаю, что это, вероятно, вопрос для суперпользователя, а не для SO. Что бы он ни сделал, он получает UTF-16-LE из своей консоли, и использование getwch решит его проблему с Python, и он не спрашивал о других проблемах… Но если вы думаете, что можете диагностировать основную проблему, это было бы даже лучше. - person abarnert; 28.04.2018
comment
Я не думаю, что формат вопросов и ответов Stack Exchange лучше всего подходит для работы с ошибками, которые могут быть вызваны широким кругом проблем. Я шел по этому пути раньше, и в основном это превращается в длинные чаты, которые продолжаются для страниц, что также в основном удваивается как учебник по использованию отладчика и других инструментов. - person Eryk Sun; 28.04.2018
comment
Многие символы (например, ∫) будут игнорироваться при вставке в консоль. Если вставленный символ не соответствует раскладке клавиатуры (VkKeyScan), не является C3_ALPHA лингвистическим (GetStringType) или не находится в восточно-азиатском диапазоне полной ширины, консоль вставляет его как OEM-последовательность Alt+Numpad ( или две последовательности для не-BMP), т. е. закодировать как OEM (обычно как по умолчанию?), преобразовать в десятичную строку и вставить последовательность ключевых событий. Последнее нажатие клавиши Alt имеет фактическое значение символа Unicode. Функция CRT getwch не поддерживает эту вставленную последовательность ключевых событий. - person Eryk Sun; 28.04.2018
comment
Обратите внимание, что эта последовательность клавиш Alt+Numpad наблюдается только при низкоуровневом вызове ReadConsoleInput, используемом getwch. Для высокоуровневых вызовов ReadConsole и ReadFile консоль включает только фактический символ Unicode (или суррогатную пару для не-BMP). - person Eryk Sun; 28.04.2018