【问题标题】:Why does the traceback print earlier than print url?为什么回溯打印早于打印网址?
【发布时间】:2019-07-30 06:29:13
【问题描述】:

据我所知,在运行以下代码时,print(url, end='') 将首先打印一行。

然后requests.get(url) 引发异常,触发traceback.print_exc()

但在我的测试中,traceback.print_exc() 早于print(url, end='') 在屏幕上打印。

为什么?

另一方面,如果我将traceback.print_exc() 替换为print('error occurred'),它会按照我的想法工作。

好像traceback.print_exc()的优先级更高?

import traceback

import requests


url = 'http://www.szwb.gov.cn/wap/jggk/gzdt/201809/t20180919_14099889.htm'

try:
    print(url, end='')
    response = requests.get(url)
    # balabala
except Exception as e:
    traceback.print_exc()
    # print('error occurred.')

【问题讨论】:

    标签: python traceback


    【解决方案1】:

    print 将输出到 STDOUT,traceback.print_exc() 将输出到 STDERR。 STDOUT 是“缓冲的”,而 STDERR 不是。来自this article

    默认情况下,程序中的 I/O 是缓冲的,这意味着 IO 不会立即逐字节提供服务,而是从临时存储中提供给请求程序...通过缓冲,整个块被读入缓冲区一次然后各个字节从(内存中的快速)缓冲区传递给您。

    当缓冲区被“刷新”时,它会被显示出来。通常,如果输出是终端,缓冲区会刷新到新的一行。

    在 Python 3 中,您可以使用 flush kwarg 强制执行此操作:

    print(url, end='', flush=True)
    

    实际上等同于:

    import sys
    
    # ...
    
    print(url, end='')
    sys.stdout.flush()
    

    或者,您可以删除end kwarg:

    print(url)
    

    请注意,这将在 URL 之后打印一个换行符。这可能是不可取的。

    【讨论】:

    • 我欢迎扩展或更正此答案的 cmets。
    【解决方案2】:

    对于控制台的 I/O,通常在 python 中进行缓冲。并且发送错误报告的 I/O 对 print 函数调用具有更高的优先级。

    也就是说, print(url, end='')首先将其数据放入缓冲区。然后错误报告将其数据放入缓冲区。

    当错误报告放入其数据时,打印函数的数据仍在缓冲区中,优先级较低。所以错误报告把它的数据放在它前面并显示在它前面。

    【讨论】:

    • 这个有来源吗?
    • 请查看python.sys。打印电话sys.stdouttraceback.print_exc() 电话sys.stderr。交互时,stdout 和 stderr 流是行缓冲的。没有定义哪个具有更高的优先级。但对于大多数人来说,stderr 确实如此。
    • 很有趣,谢谢!似乎 Python 2 在这方面与 Python 3 有很大不同。
    猜你喜欢
    • 2021-02-13
    • 1970-01-01
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 2014-03-23
    相关资源
    最近更新 更多