如何在Python中检测ESCape keypress?

时间:2021-12-11 05:40:31

I am running a process in a command window (Windows 7, Python 3.1) where I would like the user to abort the process by pressing the ESCape key. However, pressing the ESCape key doesn't appear to do anything :-(, the loop never breaks. I have also tried running the script from within my IDE (Wing), but again, the loop cannot be interrupted.

我正在命令窗口(Windows 7,Python 3.1)中运行一个进程,我希望用户通过按ESCape键来中止该进程。但是,按ESCape键似乎没有做任何事情:-(,循环永远不会中断。我也尝试从我的IDE(Wing)中运行脚本,但同样,循环不能被中断。

The following is a stripped-down version of my proof-of-concept test...

以下是我的概念验证测试的精简版...

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!

If anyone could tell me where I might be going wrong I would be most grateful.

如果有人能告诉我哪里可能出错了,我将非常感激。

5 个解决方案

#1


5  

Python 3 strings are unicode and, therefore, must be encoded to bytes for comparison. Try this test:

Python 3字符串是unicode,因此必须编码为字节以进行比较。试试这个测试:

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

Or this test:

或者这个测试:

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

Or this test:

或者这个测试:

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

#2


4  

You should really strip down more, like this one below:

你真的应该删除更多,如下所示:

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

So here is the problem: msvcrt.getch() returns bytes, chr(27) returns string. In Python 3 they are two distinct types, so the "==" part will never work, and the if statement will always be evaluated as False.

所以这就是问题:msvcrt.getch()返回字节,chr(27)返回字符串。在Python 3中,它们是两种不同的类型,因此“==”部分将永远不会起作用,并且if语句将始终被评估为False。

The solution should be obvious to you.

解决方案应该是显而易见的。

More about strings vs bytes, from the book Dive into Python 3.

有关字符串与字节的更多信息,请参阅“潜入Python 3”一书。

The interactive console is very useful for debugging, try use it more :)

交互式控制台对于调试非常有用,请尝试使用它:)

#3


4  

You don't need encode, decode, chr, ord, ....

你不需要编码,解码,chr,ord,....

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

or if you'd like to see "27" in the code somewhere:

或者如果你想在代码中看到“27”:

if msvcrt.kbhit() and msvcrt.getch()[0] == 27:

#4


2  

Python 2/3 compatible code:

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)

Code parts are taken from pager module with more stuff inside.

代码部分取自寻呼机模块,内部有更多内容。

#5


1  

Have you tried using a different key to test if it's not just that key?

您是否尝试使用其他密钥来测试它是否不仅仅是那个密钥?

Did you also try the examples at (http://effbot.org/librarybook/msvcrt.htm) to see if they worked?

您是否也尝试过(http://effbot.org/librarybook/msvcrt.htm)的示例,看看它们是否有效?

#1


5  

Python 3 strings are unicode and, therefore, must be encoded to bytes for comparison. Try this test:

Python 3字符串是unicode,因此必须编码为字节以进行比较。试试这个测试:

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

Or this test:

或者这个测试:

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

Or this test:

或者这个测试:

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

#2


4  

You should really strip down more, like this one below:

你真的应该删除更多,如下所示:

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

So here is the problem: msvcrt.getch() returns bytes, chr(27) returns string. In Python 3 they are two distinct types, so the "==" part will never work, and the if statement will always be evaluated as False.

所以这就是问题:msvcrt.getch()返回字节,chr(27)返回字符串。在Python 3中,它们是两种不同的类型,因此“==”部分将永远不会起作用,并且if语句将始终被评估为False。

The solution should be obvious to you.

解决方案应该是显而易见的。

More about strings vs bytes, from the book Dive into Python 3.

有关字符串与字节的更多信息,请参阅“潜入Python 3”一书。

The interactive console is very useful for debugging, try use it more :)

交互式控制台对于调试非常有用,请尝试使用它:)

#3


4  

You don't need encode, decode, chr, ord, ....

你不需要编码,解码,chr,ord,....

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

or if you'd like to see "27" in the code somewhere:

或者如果你想在代码中看到“27”:

if msvcrt.kbhit() and msvcrt.getch()[0] == 27:

#4


2  

Python 2/3 compatible code:

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)

Code parts are taken from pager module with more stuff inside.

代码部分取自寻呼机模块,内部有更多内容。

#5


1  

Have you tried using a different key to test if it's not just that key?

您是否尝试使用其他密钥来测试它是否不仅仅是那个密钥?

Did you also try the examples at (http://effbot.org/librarybook/msvcrt.htm) to see if they worked?

您是否也尝试过(http://effbot.org/librarybook/msvcrt.htm)的示例,看看它们是否有效?