使用Python C API开发扩展时如何刷新stdout与stderr输出流?
C编写Python扩展时刷新PySys输出流的实现方法
核心原理
PySys_WriteStdout、PySys_WriteStderr写入的是Python层包装的sys.stdout、sys.stderr流,和C标准库的stdout/stderr不是同一层面的对象,不能直接调用C的fflush实现刷新,需要通过Python的流接口操作。
实现方案
方案1:全版本通用兼容方案
适用于所有Python3版本,通过调用sys.stdout.flush()和sys.stderr.flush()的C API实现:
// 刷新标准输出流 PyObject* sys_mod = PyImport_ImportModule("sys"); if (sys_mod) { PyObject* stdout = PyObject_GetAttrString(sys_mod, "stdout"); if (stdout) { PyObject* flush_res = PyObject_CallMethod(stdout, "flush", NULL); Py_XDECREF(flush_res); Py_DECREF(stdout); } Py_DECREF(sys_mod); } // 刷新标准错误流 PyObject* sys_mod_err = PyImport_ImportModule("sys"); if (sys_mod_err) { PyObject* stderr = PyObject_GetAttrString(sys_mod_err, "stderr"); if (stderr) { PyObject* flush_res = PyObject_CallMethod(stderr, "flush", NULL); Py_XDECREF(flush_res); Py_DECREF(stderr); } Py_DECREF(sys_mod_err); }
如果你的代码已经持有sys模块的引用,可以省略重复导入的步骤,直接使用即可。
方案2:Python3.10+简化方案
Python3.10及以上版本官方新增了专用C API,直接调用即可:
- 刷新标准输出:
PySys_FlushStdout() - 刷新标准错误:
PySys_FlushStderr()
两个函数调用成功返回0,出现异常返回-1,无需手动处理对象引用,使用更简洁。
注意事项
禁止直接调用C标准库的
fflush(stdout)/fflush(stderr)操作,该操作只会刷新C层面的输出流,不会处理Python层的缓冲,可能导致输出不生效、顺序混乱等问题。
内容的提问来源于stack exchange,提问作者anymous.asker
相关产品推荐
相关产品推荐

