2014-01-13 73 views
12

我有一個執行的函數以下(除其他事項外):sys.stdin.readline()讀取無提示,返回「沒什麼」之間

userinput = stdin.readline() 
betAmount = int(userinput) 

應該採取輸入整數作爲標準輸入一個字符串並將其轉換爲整數。

當我打電話的功能,但是,它返回一個換行符(它甚至不等待我輸入任何東西)。

在節目早些時候,我得到一些輸入形式:

stdin.read(1) 

捕捉單個字符。

可這有什麼關係呢?我以某種方式爲標準輸入的下一行寫了一個換行符?

我該如何解決這個問題?

回答

21

stdin.read(1)讀取stdin一個字符。如果有在該點被讀取多於一個字符(例如隨後所讀取的一個字符的新行),那麼一個或多個字符將仍然是在緩衝等待下一read()readline()

舉個例子,給出rd.py

from sys import stdin 

x = stdin.read(1) 
userinput = stdin.readline() 
betAmount = int(userinput) 
print ("x=",x) 
print ("userinput=",userinput) 
print ("betAmount=",betAmount) 

...如果我運行此腳本如下(我已經在234類型):

C:\>python rd.py 
234 
x= 2 
userinput= 34 

betAmount= 34 

......所以, 2首先被拾起,留下34和尾隨的換行符被readline()拾取。

我建議在大多數情況下,通過使用readline()而不是read()來解決問題。

+1

@volcano總結這個非常漂亮的我,謝謝你們 – lightandlight

0

嘗試......當您按下一個字符

import sys 
buffer = [] 
while True: 
    userinput = sys.stdin.readline().rstrip('\n') 
    if userinput == 'quit': 
     break 
    else: 
     buffer.append(userinput) 
3
stdin.read(1) 

不會返回 - 它會等待 '\ n'。問題是第二個字符在標準輸入中被緩衝,當你調用另一個輸入時 - 它會立即返回,因爲它從緩衝區獲得輸入。

+0

簡明explanation-謝謝 – lightandlight

-1
import sys 
userinput = sys.stdin.readline() 
betAmount = int(userinput) 

print betAmount 

這工作我的系統上。我檢查INT('23 \ n「)將導致23

+0

經過與Python 2.7 .. – Jagat

+0

如果你讀了整個問題,你是不是測試了什麼,他的doing-的重要組成部分在sys.stdin.readline()之前調用'sys.stdin.read(1)',所以你的代碼工作並不意味着什麼。 (另外,OP的代碼是Python 3;爲什麼你會在2.7中測試它,然後假設它是一樣的?) – abarnert

10

西蒙的回答和火山的共同解釋你在做什麼錯了,西蒙解釋瞭如何通過重新設計的界面解決它。

但如果你真的需要讀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樣式的命令鍵等來編輯他的輸入項,那麼你會把所有那些作爲原始的按鍵,你不想處理。

+0

'sys.stdin.buffer.raw'將不會緩衝進程另一端的stdout緩衝區在非tty情況下,當塊緩衝可能用於標準輸出時,也就是說,您將無法從Python讀取任何內容,直到其他進程刷新其標準輸出緩衝區爲止。 – jfs

0

如果您只需要一個字符,並且您不想將事物保存在緩衝區中,則可以簡單地讀取整行並放棄不需要的所有內容。

替換:

stdin.read(1) 

stdin.readline().strip()[:1] 

這將讀取一行,刪除空格和換行,並只保留第一個字符。

相關問題