Python 3中__future__模块中print_function的奇怪行为

2 投票
2 回答
1417 浏览
提问于 2025-04-17 14:26

我观察到在Python 3.2中,__future__模块的print_function有个奇怪的表现。

举个例子,这段代码:

from __future__ import print_function
import sys

print('Enter the base path of the images: ', end='')
path = sys.stdin.readline().strip().strip('"')
if len(path) == 0:
    print("No path entered")
else:
    print(root)
print("\n\nPress ENTER to exit")
exit = sys.stdin.readline()

当运行这个脚本时,控制台似乎要等用户按下ENTER键后才会显示第一个print语句。
输出看起来是这样的:


Enter the base path of the images: No path entered


Press ENTER to exit

显然,给用户显示一个空的提示会让人很困惑,尤其是很多人对黑色窗口里的白色文字(命令提示符)感到害怕。

当代码改成这样:

from __future__ import print_function
import sys

print('\nEnter the base path of the images: ', end='') #line now starts with \n
path = sys.stdin.readline().strip().strip('"')
if len(path) == 0:
    print("No path entered")
else:
    print(path)
print("\n\nPress ENTER to exit")
exit = sys.stdin.readline()

那么输出就如预期那样了(假设我们忽略前面的空行):


Enter the base path of the images: c:\
c:\


Press ENTER to exit

不过在Python 2.6中,第一种情况却能正常工作(也就是说,它会在等待输入之前显示Enter the base path of the images:)。

这让我想问:
为什么在Python 3.2中,我需要在print函数前加一个\n才能显示输出,而在Python 2.6中却不需要这个\n
这是否意味着print_function在这两个版本中的实现方式不同?

2 个回答

2

在这种情况下,我会先检查一下我的Python版本,然后用合适的“输入”函数替换掉原来的函数。现在你可以在任何需要用户输入的地方直接使用input了。

from __future__ import print_function
import sys

if sys.version_info < (3,):
    input = raw_input

path = input('Enter the base path of the images> ').strip().strip('"')
if len(path) == 0:
    print("No path entered")
else:
    print(path)

print("\n\nPress ENTER to exit")
exit = input()
5

你看到的现象是因为使用了行缓冲。首先要刷新一下 stdout(可以用 sys.stdout.flush(),这样在 Python 2 中也能兼容使用):

print('Enter the base path of the images: ', end='')
sys.stdout.flush()

Python 2 的 print() 函数和 Python 3 的确是有区别的(在 Python 3 中,from __future__ import print_function 这一行基本上没有意义)。在 Python 3 中,输入输出的处理方式进行了大改动,stdout 的缓冲机制也有了细微的变化。在 Python 2 中,调用 sys.stdin.readline() 会自动刷新 stdout,但在 Python 3 中就不再这样了。

如果你使用 input() 函数,而不是直接从 stdin 读取,那么你根本不需要手动刷新:

msg = 'Enter the base path of the images: '
try:
    # python 2
    path = raw_input(msg)
except NameError:
    # python 3
    path = input(msg)

撰写回答