2014-10-19 83 views
1

我必須寫,不知怎的,同時適用於Python版本代碼的蟒蛇行爲,我無法理解的代碼的行爲:當我運行的代碼解釋這個python3 VS sys.stdin

from __future__ import print_function 
import sys 
sys.stdout.flush() 
print("input: ", end="") 
f = sys.stdin.readline() 
print(f) 

與python2它的行爲就像我所期望的:

$ python2 test_input.py 
input: foo bar 
foo bar 

當我用python3運行代碼它表現奇怪。它首先讀取輸入 然後打印提示:

$ python3 test_input.py 
foo bar 
input: foo bar 

你能解釋這一點,並提出一個解決?

+0

Python 3中的I/O子系統是一次徹底的檢修(請參閱'io'模塊,也可以在Python 2中使用),所以沖洗行爲可能已經改變並不令人驚奇。 – 2014-10-19 10:03:05

+0

@MartijnPieters,實際上,Dietrich Epp的解決方案是可行的。 – Oz123 2014-10-19 10:06:58

+0

@MartijnPieters,你會怎麼做? – Oz123 2014-10-19 10:07:27

回答

2

你讓你的flush()print()倒退。下面是正確的順序:

# First, write to stdout 
print("input: ", end="") 
# Then, flush all data in the stdout buffer 
sys.stdout.flush() 
+0

我認爲那是*點*。 OP顯示'stdout'已經被手動刷新,之後行爲上的差異是意外的。 – 2014-10-19 10:03:52

+0

@MartijnPieters:在緩衝區中什麼都不會調用'flush()'什麼? – 2014-10-19 10:04:27

+0

要產生一個最小的,可驗證的測試用例來證明行爲? – 2014-10-19 10:04:45

0

在Python 3.3 flush關鍵字添加到print() function

Changed in version 3.3: Added the flush keyword argument.

在版本3.3之前,該print()函數將總是沖洗,使用end=''即使。

$ python3.2 test.py 
foo bar 
input: foo bar 

要獲得相同的行爲,在Python 3.3沖洗:

try: 
    print("input: ", end="", flush=True) 
except TypeError: 
    print("input: ", end="") 

或Python的3.3或以上版本使用了sys.stdout.flush()print()調用你的確切行爲也使用Python 3.2再現。

+0

「或在'print()'調用」之後使用'sys.stdout.flush()'...你不是在回答我的抱怨嗎? – 2014-10-19 10:09:27

+0

@DietrichEpp:我在抱怨你的*診斷*。我說的是沖洗是第一次**故意**。我從來沒有說過它不會解決問題。 OP要求我們解釋**爲什麼** Py 2和Py 3之間存在差異。 – 2014-10-19 10:10:04

2

的區別在於CPython的2使用C STDIO實現標準流,如sys.stdinsys.stdout(由print()使用)而Python 3重新實現IO上系統API的頂部例如,打開,讀,寫上POSIX。

# __main__.py 
import sys 

sys.stdout.write("input: ") 
f = sys.stdin.readline() 
sys.stdout.write("*" + f) 

關於Python 3 "input: "是不readline()調用之前打印:

$ python2 . 
input: foo bar 
*foo bar 
$ python3 . 
foo bar 
input: *foo bar 

爲了避免在思考如何print()實現,如果sys.stdout直接使用時會發生同樣的問題C,stdout在讀取交互式案例中的任何輸入之前被刷新(如果輸出操作之後是在沒有01的同一更新流上進行輸入操作,則這是未定義的行爲之間)。這個C程序打印"input: "要求輸入作爲之前的預期:

#include <stdio.h> 

#define MAXLEN 100 

int main(void) { 
    char buf[MAXLEN] = {0}; 

    fputs("input: ", stdout); 
    if (!fgets(buf, MAXLEN, stdin)) 
    return 1; 

    fputs(buf, stdout); 
    return 0; 
} 

這就是爲什麼解決方法:在調用sys.stdout.flush()sys.stdin.readline()suggested by @Dietrich Epp作品。

這是Python 3實現中的一個缺陷。如果兩者都指向同一位置(os.path.samefile(sys.stdout.fileno(), sys.stdin.fileno()),例如,如果兩個都是tty),則stdin在默認情況下從stdin讀取之前將被刷新。你可以report the issue at Python bug tracker