为什么回溯打印早于打印 url?

Why does the traceback print earlier than print url?

据我所知,当运行下面的代码时,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.')

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

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

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

print 将输出到 STDOUT,traceback.print_exc() 将输出到 STDERR。 STDOUT 是 "buffered" 而 STDERR 不是。来自 this article:

By default, I/O in programs is buffered which means the IO is not served immediately byte by byte rather are served from a temporary storage to the requesting program... By buffering, the whole block is read into the buffer at once then the individual bytes are delivered to you from the (fast in-memory) buffer area.

当缓冲区为"flushed"时,会显示出来。通常,如果输出是终端,缓冲区会在新行刷新。

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

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

实际上等同于:

import sys

# ...

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

或者,您可以删除 end kwarg:

print(url)

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