我必须编写一个代码,以某种方式适用于两个python版本,我无法理解代码的行为:
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 :(得分:2)
你的flush()
和print()
倒退了。这是正确的顺序:
# First, write to stdout
print("input: ", end="")
# Then, flush all data in the stdout buffer
sys.stdout.flush()
答案 1 :(得分:2)
不同之处在于CPython 2使用C stdio实现标准流,例如sys.stdin
,sys.stdout
(由print()
使用),而Python 3在系统API上重新实现IO,例如,打开,阅读,写在POSIX上。
为避免考虑如何实施print()
,如果直接使用sys.stdout
则会出现同样的问题:
# __main__.py
import sys
sys.stdout.write("input: ")
f = sys.stdin.readline()
sys.stdout.write("*" + f)
在Python "input: "
调用之前未打印{3}}:
readline()
在C中,在读取交互式案例中的任何输入之前刷新$ python2 .
input: foo bar
*foo bar
$ python3 .
foo bar
input: *foo bar
(如果输出操作之后是同一更新流上的输入操作,而其间没有stdout
,那么它是未定义的行为) 。在按预期要求输入之前,此C程序打印fflush()
:
"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;
}
suggested by @Dietrich Epp之前调用sys.stdout.flush()
。
这是Python 3实现的一个缺陷。如果两者都指向相同的位置(sys.stdin.readline()
,例如,如果两者都是tty),则在从stdin读取之前默认刷新stdout。你可以report the issue at Python bug tracker。
答案 2 :(得分:0)
在Python 3.3中flush
关键字被添加到print()
function:
在版本3.3中更改:添加了flush关键字参数。
在3.3之前的版本中,print()
函数总是刷新,即使使用end=''
也是如此。您的确切行为也使用Python 3.2重现:
$ python3.2 test.py
foo bar
input: foo bar
要获得相同的行为,请在Python 3.3中刷新:
try:
print("input: ", end="", flush=True)
except TypeError:
print("input: ", end="")
或sys.stdout.flush()
调用Python 3.3或更高版本后使用print()
。