Search code examples
pythonpython-3.xstdoutpython-3.7stderr

Python prints messages not sequentially


if I have this code

def soft_assert(condition):
    if not condition:
        print('start')
        traceback.print_stack()
        print('finish')

soft_assert(False)
soft_assert(False)

the output is different every time I run it:

  File "/Users/spleshakov/Documents/api-testing-with-pytest/tenants/test_uc.py", line 38, in <module>
    soft_assert(False, 'message 1')
  File "/Users/spleshakov/Documents/api-testing-with-pytest/tenants/test_uc.py", line 30, in soft_assert
    traceback.print_stack()
  File "/Users/spleshakov/Documents/api-testing-with-pytest/tenants/test_uc.py", line 41, in <module>
    soft_assert(False, 'message 4')
  File "/Users/spleshakov/Documents/api-testing-with-pytest/tenants/test_uc.py", line 30, in soft_assert
    traceback.print_stack()
start
finish
start
finish

or

start
finish
start
finish
  File "/Users/spleshakov/Documents/api-testing-with-pytest/tenants/test_uc.py", line 38, in <module>
    soft_assert(False)
  File "/Users/spleshakov/Documents/api-testing-with-pytest/tenants/test_uc.py", line 30, in soft_assert
    traceback.print_stack()
  File "/Users/spleshakov/Documents/api-testing-with-pytest/tenants/test_uc.py", line 41, in <module>
    soft_assert(False)
  File "/Users/spleshakov/Documents/api-testing-with-pytest/tenants/test_uc.py", line 30, in soft_assert
    traceback.print_stack()

The output can be in any order you can think of

This doesn't make sense to me, I can't find an answer, so I was hoping the community can help me with these questions:

  1. Why this is happening?
  2. How do I make wait one print to finish, before doing another one?

Thanks


Solution

  • The problem is it prints by default to the stderr, not the stdout:

    # Used by print_stack
    def print_list(extracted_list, file=None):
        if file is None:  # Note here
            file = sys.stderr
        for item in StackSummary.from_list(extracted_list).format():
            print(item, file=file, end="")
    

    You're getting out-of-order output because the two streams are being printed to the same console at once.

    Specify the file argument so it all gets printed to the same stream:

    from sys import stdout
    
    def soft_assert(condition):
        if not condition:
            print('start')
            traceback.print_stack(file=stdout)  # Print to stdout
            print('finish')