西蒙的回答和火山的共同解釋你在做什麼錯了,西蒙解釋瞭如何通過重新設計的界面解決它。
但如果你真的需要向讀1個字符,再後來讀1線,你可以做到這一點。這不是微不足道的,它在Windows上與其他一切不同。
實際上有三種情況:在任一平臺上有Unix tty,Windows DOS提示符或常規文件(重定向文件/管道)。你必須以不同的方式處理它們。
首先,要檢查stdin是否是tty(包括Windows和Unix版本),請致電sys.stdin.isatty()
。這部分是跨平臺的。
對於非tty的情況,這很容易。它實際上可能只是工作。如果沒有,您可以從sys.stdin
下面的無緩衝對象讀取。在Python 3中,這隻意味着sys.stdin.buffer.raw.read(1)
和sys.stdin.buffer.raw.readline()
。但是,這會得到編碼的字節而不是字符串,因此您需要在結果上調用.decode(sys.stdin.decoding)
;你可以將它們全部包裝在一個函數中。
但是,對於Windows上的tty情況,即使在原始緩衝區上,輸入仍然會被行緩衝。唯一的解決方法是使用Console I/O函數,而不是普通的文件I/O。所以,而不是stdin.read(1)
,你做msvcrt.getwch()
。
對於Unix上的tty案例,您必須將終端設置爲原始模式,而不是通常的行紀律模式。一旦你這樣做了,你可以使用相同的sys.stdin.buffer.read(1)
等,它就會工作。如果你願意永久這樣做(直到你的腳本結束),這很容易,tty.setraw
功能。如果您想稍後返回到行紀模式,則需要使用termios
模塊。這看起來很可怕,但如果你在調用setraw
之前隱藏了termios.tcgetattr(sys.stdin.fileno())
的結果,那麼做termios.tcsetattr(sys.stdin.fileno(), TCSAFLUSH, stash)
,你不必知道所有這些煩人的位是什麼意思。
在這兩個平臺上,調音臺I/O和原始終端模式都很痛苦。如果你曾經做過任何控制檯/原始閱讀,你肯定不能使用sys.stdin
緩衝區;您只能使用sys.stdin.buffer.raw
。你總是可以通過逐字符讀取來代替readline
,直到你得到一個換行符,但是如果用戶試圖通過使用退格鍵,箭頭,emacs樣式的命令鍵等來編輯他的輸入項,那麼你會把所有那些作爲原始的按鍵,你不想處理。
@volcano總結這個非常漂亮的我,謝謝你們 – lightandlight