How to flush <stdio.h>'s stdout stream?

Eryk Sun eryksun at gmail.com
Fri Jan 15 15:31:31 EST 2021


On 1/15/21, Grant Edwards <grant.b.edwards at gmail.com> wrote:
> In Python 3.7+, how does one flush the stdout FILE stream? I mean the
> FILE *declared as 'stdio' in <stdio.h>. I'm _not_ asking how to flush the
> Python file object sys.stdio.

You can flush all output streams via C fflush(NULL). If it has to be
just stdout, the code will vary by platform. As far as I know, there
is no standard way at the ABI level to reference C stdin, stdout, and
stderr. Typically these are macros at the API level. The macro might
directly reference the FILE record, or maybe it calls an inline
function that returns the reference. CPython doesn't have a common
wrapper function for this. With ctypes, you'll have to special case
common platform CRTs such as glibc in Linux and ucrt in Windows
(possible, but undocumented). For example:

    import sys
    import time
    import ctypes

    if sys.platform == 'win32' and sys.version_info >= (3, 5):
        libc = ucrt = ctypes.CDLL('ucrtbase', use_errno=True)
        IOLBF = 0x0040
        libc.__acrt_iob_func.restype = ctypes.c_void_p
        stdout = ctypes.c_void_p(libc.__acrt_iob_func(1))
    elif sys.platform == 'linux':
        libc = cglobal = ctypes.CDLL(None, use_errno=True)
        IOLBF = 1
        stdout = ctypes.c_void_p.in_dll(libc, 'stdout')

    # ensure that stdout is buffered for this test
    # has to be called before stdout is used
    libc.setvbuf(stdout, None, IOLBF, 4096)

    def test(flush=False):
        print(f'test with flush={flush}')
        libc.fwrite(b'spam', 1, 4, stdout)
        if flush:
            libc.fflush(stdout)
        time.sleep(5)
        libc.fflush(None)
        print()

    test(flush=False)
    test(flush=True)

With flush=False, the test should wait 5 seconds before 'spam' is
flushed to the console/terminal. With flush=True, there should be no
delay.


More information about the Python-list mailing list