解释这个python3与sys.stdin的python行为

时间:2014-10-19 10:00:54

标签: python python-3.x python-2.x

我必须编写一个代码,以某种方式适用于两个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

你能解释一下并建议修复吗?

3 个答案:

答案 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.stdinsys.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()