好奇的python打印行为

时间:2017-04-10 20:10:24

标签: python scripting interpreter

我在python 2.7脚本中使用了print语句,我在其中创建了数据建模类的实例。它们是相当大的类,它们在init期间在属性设置器中执行大量计算,因此它不是执行速度最快的脚本。我使用print语句来了解进度,但有趣的是它们如何执行。代码看起来像这样:

    from __future__ import absolute_import, division, print_function, unicode_literals

    print('Loading data...', end='\t')
    data = LoadData(data_path)
    first_model = FirstModel(parameters).fit(data)
    print('Done.\nFitting second model...', end='\t')
    # prints 'Done.' and then there's a very long pause...
    # suddenly 'Fitting second model...' prints and the next model initializes almost immediately
   second_model = SecondModel(parameters).fit(data)
   results = second_model.forecast(future_dates)

为什么声明print('Done.\nFitting second model...', end=\t')首先打印'完成。'然后停顿很长一段时间?我运行此代码时有一个实例,在“完成”之后。'打印我在打印的其余部分之前收到错误。返回的错误是SecondModel中的错误,我在其中尝试访问方法作为属性。这里发生了什么? python如何或以何种方式以违反直觉的方式执行此print语句?好像解释器将新行字符视为表示它应该开始查看代码的后续部分。

1 个答案:

答案 0 :(得分:2)

默认情况下,print调用是缓冲的。只要遇到换行符,就会刷新缓冲区(因此,您会看到Done\n出现)。但是,后续文本将保留在缓冲区中,直到下一个刷新它的事件为止(在没有要打印的后续换行符的情况下,可能是Python要么返回命令提示符要么完全退出到shell,取决于您如何运行此脚本)。因此,对SecondModel().fit()的耗时调用正在两行的显示之间发生。

为避免这种情况,您可以在sys.stdout.flush()之后立即调用print来手动刷新缓冲区。或者,如果你曾经转向Python 3.3或更高版本,你可以通过将附加参数flush=True传递给print()来快捷方式。

错误消息可以中断print输出,反之亦然,因为默认情况下它们分别由两个独立的流处理:sys.stderrsys.stdout。这两个流有不同的缓冲区。