Search code examples
pythontraceback

Why does the traceback print earlier than print url?


As I know when running the following code, the print(url, end='') will first print a line.

Then requests.get(url) raise an exception, which triggers the traceback.print_exc().

But in my test, the traceback.print_exc() print on the screen earlier than print(url, end='').

Why?

On the other hand if I replace the traceback.print_exc() with print('error occurred'), it works as what I thought.

Seems that the traceback.print_exc() has a higher priority?

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.')

Solution

  • print will output to STDOUT and traceback.print_exc() will output to STDERR. STDOUT is "buffered" and STDERR is not. From 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.

    When the buffer is "flushed", it will be displayed. Normally, if the output is a terminal, the buffer is flushed at a new line.

    In Python 3, you can force this with the flush kwarg:

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

    Which is effectively the same as:

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

    Alternatively, you can remove the end kwarg:

    print(url)
    

    Note that this will print a newline after the URL. This could be undesirable.