Python 3中__future__模块中print_function的奇怪行为
我观察到在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 个回答
在这种情况下,我会先检查一下我的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()
你看到的现象是因为使用了行缓冲。首先要刷新一下 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)