【问题标题】:Curious behaviour of print_function in __future__ module on Python 3Python 3 上 __future__ 模块中 print_function 的奇怪行为
【发布时间】:2013-11-17 19:08:23
【问题描述】:

我在 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 退出

今天不必要,向用户显示一个空提示会导致很多混乱,尤其是因为很多人害怕带有白色文本的黑色窗口(命令提示符)。

代码改成这个的时候

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()

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

输入图像的基本路径:c:\ C:\ 按 ENTER 退出

但是,当代码在 python 2.6 中运行时,第一个代码按预期工作(即它显示 Enter the base path of the images: 等待接收输入)。

这让我问:
为什么我需要在 print 函数前面加上 \n 才能在 Python 3.2 中显示输出,而在 Python 2.6 中运行时我不需要 \n
难道是print_function在两个版本中的实现方式不同?

【问题讨论】:

  • 您使用sys.stdin.readline() 而不是input 有什么原因吗?大概是为了python2.x的兼容性?
  • input 在 Python 2 中尝试评估输入的任何内容(不是我想要的)。在 Python 3 中,它只是捕获输入(我想要的)。 raw_input 捕获输入(我想要的),但它只适用于 Python 2,而不是 3,所以很不方便。使用sys.stdin.readline() 允许我在两个版本中使用相同的函数调用。

标签: python python-import


【解决方案1】:

您正在看到行缓冲的效果。首先刷新stdout(使用sys.stdout.flush() 以向后兼容Python 2):

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

Python 2 中的 print() 函数肯定与 Python 3 中的函数不同(from __future__ import print_function 行实际上毫无意义)。在 Python 3 中,I/O 已经过大修,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)

【讨论】:

  • 这也是我制定的解决方案——除了我是 LBYL——if sys.version_info < (3,): input = raw_input ...我以这种方式隐藏了内置的 input——但我并不太愿意关于那个的形状;-)
  • Python 3 不会完全忽略未来的导入:它仍然会将当前范围内的名称“print_function”绑定到导入的值。在 Python 3 中,该导入没有任何神奇的含义。
  • @Duncan:我是不是又错过了“有效”这个词? :-P
  • 由于调用input(或Python 2 中的raw_input)会刷新输出缓冲区,因此我将input 函数重新分配给一个基于python 运行版本的通用函数if sys.version_info[0] == 2: input = raw_input .现在我调用一个函数来刷新和收集用户的输入,而不管执行脚本的 python 版本如何。
【解决方案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()

【讨论】:

  • 附带说明一下,使用上面发布的代码,您甚至不再需要未来的导入——使此代码与 MUCH 甚至比 2.6 更旧的 python 版本一起工作。 -- 可能回到python2.0 ...
猜你喜欢
  • 2019-08-25
  • 2020-07-06
  • 2020-08-27
  • 1970-01-01
  • 2016-07-09
  • 2022-11-14
  • 1970-01-01
  • 2022-08-23
  • 2021-04-29
相关资源
最近更新 更多