Как обнаружить нажатие клавиши ESCape в Python? - PullRequest
8 голосов
/ 28 февраля 2011

Я запускаю процесс в командном окне (Windows 7, Python 3.1), где я бы хотел, чтобы пользователь прервал процесс, нажав клавишу ESCape. Однако нажатие клавиши ESCape, похоже, ничего не делает :-(, цикл никогда не прерывается. Я также пытался запустить скрипт из моей IDE (Wing), но опять же, цикл не может быть прерван.

Ниже приведена сокращенная версия моего теста для проверки концепции ...

import msvcrt
import time

aborted = False

for time_remaining in range(10,0,-1):
    # First of all, check if ESCape was pressed
    if msvcrt.kbhit() and msvcrt.getch()==chr(27):
        aborted = True
        break

    print(str(time_remaining))       # so I can see loop is working
    time.sleep(1)                    # delay for 1 second
#endfor timing loop

if aborted:
    print("Program was aborted")
else:
    print("Program was not aborted")

time.sleep(5)  # to see result in command window before it disappears!

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

Ответы [ 5 ]

6 голосов
/ 28 февраля 2011

Строки Python 3 являются Unicode и, следовательно, должны быть закодированы в байтах для сравнения.Попробуйте этот тест:

if msvcrt.kbhit() and msvcrt.getch() == chr(27).encode():
    aborted = True
    break

Или этот тест:

if msvcrt.kbhit() and msvcrt.getch().decode() == chr(27):
    aborted = True
    break

Или этот тест:

if msvcrt.kbhit() and ord(msvcrt.getch()) == 27:
    aborted = True
    break
5 голосов
/ 28 февраля 2011

Вам не нужно кодировать, декодировать, chr, ord, ....

if msvcrt.kbhit() and msvcrt.getch() == b'\x1b':

или если вы хотите, чтобы где-то в коде было "27":

if msvcrt.kbhit() and msvcrt.getch()[0] == 27:
4 голосов
/ 28 февраля 2011

Вы должны по-настоящему раздеться, как показано ниже:

>>> import msvcrt
>>> ch = msvcrt.getch()
# Press esc
>>> ch
b'\x1b'
>>> chr(27)
'\x1b'
>>> ch == chr(27)
False

Так вот в чем проблема: msvcrt.getch() возвращает bytes, chr(27) возвращает string. В Python 3 это два разных типа, поэтому часть "==" никогда не будет работать, а оператор if всегда будет оцениваться как False.

Решение должно быть для вас очевидным.

Подробнее о строках и байтах из книги «Погружение в Python 3».

Интерактивная консоль очень полезна для отладки, попробуйте использовать ее подробнее:)

3 голосов
/ 19 декабря 2012

Код, совместимый с Python 2/3:

import time, sys

ESC = '\x1b'
PY3K = sys.version_info >= (3,)
if PY3K:
    from msvcrt import kbhit, getwch as _getch
else:
    from msvcrt import kbhit, getch as _getch
while not kbhit() or _getch() != ESC:
    print(time.asctime())
    time.sleep(1)

Части кода взяты из pager модуля с большим количеством элементов внутри.

1 голос
/ 28 февраля 2011

Вы пытались использовать другой ключ, чтобы проверить, является ли это не только этот ключ?

Вы также пробовали примеры в (http://effbot.org/librarybook/msvcrt.htm), чтобы посмотреть, сработали ли они?

...