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

Grant Edwards grant.b.edwards at gmail.com
Fri Jan 15 15:58:05 EST 2021


On 2021-01-15, Eryk Sun <eryksun at gmail.com> wrote:
> 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).

Brilliant! I read through the fflush() man page earlier but missed that.

fflush(NULL) should work.

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

That's what I was trying to figure out: whether 'stdio' was actually a
global symbol. On Linux it appears to be. I was afraid it was a macro
that referred indirectly to some per-thread storage or something...

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

That part I hadn't figured out. I've always used ctypes to call
functions in .so libraries that were explicitly loaded by the Python
app.




More information about the Python-list mailing list