2013-10-24 522 views
0

我正在製作一個算法,用於從鍵盤讀取輸入,並將其存儲在名爲的消息中,然後將此變量寫入文件。但是,無論用戶何時輸入,如果他按ESC鍵,我都希望執行停止,沒有任何錯誤。當按ESC鍵時,立即讓python退出程序

假設代碼:

message = raw_input() 

我有什麼補充?所以如果我在這樣一個句子中間:

My name is th 

而我打ESC,它停止?

+0

raw_input does not work that that。它會等待,直到用戶按下Enter鍵將用戶寫入變量消息的任何內容傳遞給用戶。你需要一些能夠監控每個按鍵的東西,然後如果按鍵是ESC鍵,它可以執行退出程序等操作。如果您使用的是Linux,請查看kbhit。 – jramirez

+0

順便說一句,有沒有這個標籤爲「pypy」的原因?從我所知道的情況來看,PyPy 2.1.0/2.7.3的功能與CPython 2.7.3完全相同,只是輸入內容相同,而早期版本則相同。 (PyPy3 2.1.0b1/3.2.3在至少一個平臺上的確與CPython 3.2.3有一些差異,但這只是因爲它只是一個帶有一些bug的測試版。) – abarnert

+0

我使用pypy,因爲它比CPython快,爲什麼我總是使用pypy作爲標籤。 –

回答

3

有沒有辦法做到這一點與正常輸入。 raw_input一次讀取整行。

在某些(很少)的情況下,你可以這樣做:

message = '' 
while True: 
    ch = sys.stdin.read(1) 
    if ch == '\x1b': 
     exit(0) 
    elif ch == '\n': 
     break 
    message += ch 

但總的來說,這是不行的。例如,在一個典型的Unix系統上,sys.stdin將被行緩衝,並且甚至可能通過像readline這樣的庫來饋送,以允許用戶在他前進時編輯。或者,如果您在IDLE內部運行該程序,則根本無法讀取stdin; raw_input通過彈出一個對話框詢問輸入,但你的代碼不能這樣做。

您可以在不同情況下的不同平臺上以不同方式解決該問題。


在Windows上,如果你知道你的輸入將是一個「DOS提示符」窗口(你可以用sys.stdin.isatty()檢查),你可以使用msvcrt功能。例如:

import sys, msvcrt 
assert sys.stdin.isatty(), "Can't run without a console to run on" 
message = u'' 
while True: 
    ch = msvcrt.getwche() 
    if ch == u'\x1b': 
     exit(0) 
    elif ch == u'\n': 
     break 
    message += ch 

這應該適用於這兩種2.6+和3.3+,但是在2.x中,不像raw_input,它返回一個unicode而不是str。如果您需要str,請刪除所有u前綴,並使用getche而不是getwche


在有合理的標準termios(包括Mac OS X和Linux)最POSIX般的平臺上,如果你知道你的輸入將是一個「TTY」(你可以用sys.stdin.isatty() -or檢查,如果你願意的話,你可以找一個TTY來代替標準輸入,儘管這在很多平臺上都不能工作),你可以使用[termioshttp://docs.python.org/3/library/termios.html)或tty模塊輸入到「原始」模式。在Python 3.x中,您可能必須直接從sys.stdin.buffer而不是sys.stdin中讀取,然後手動解碼爲Unicode。所以:

import sys, termios, tty 
assert sys.stdin.isatty(), "Can't run without a console to run on" 
fd = sys.stdin.fileno() 
stash = termios.tcgetattr(fd) 
try: 
    tty.setraw(fd) 
    newterm = termios.tcgetattr(fd) 
    newterm[tty.LFLAG] |= termios.ECHO 
    termios.tcsetattr(fd) 
    message = b'' 
    while True: 
     ch = sys.stdin.buffer.read(1) 
     if ch == b'\x1b': 
      exit(0) 
     elif ch == b'\n': 
      break 
     else: 
      message += ch 
    message = message.decode(sys.stdin.encoding) 
finally: 
    termios.tcsetattr(fd, termios.TCSANOW, stash) 

與Windows版本,這應該是2.6 +/3.3 +多版本兼容,除了一個事實,即它總是返回unicode而2.X raw_input將返回str(在此大小寫全部在decode行中,如果不需要,可以放棄)。

請注意,我在這裏同時使用了ttytermiostty模塊是一個更高級別的包裝,但它不會做你想做的一切。因此,您可以儘可能使用它(翻轉需要的任何開關以在您的平臺上獲取原始模式,並讓您爲標記集和值使用跨平臺/可讀名稱而不是索引),但通常無論如何還是需要termios


在任何其他平臺上,你是自己的。