Python: flush stdout and stderr after running Python script

When debugging with gdb in vscode, the stuff I print when executing a script in
the text editor does not show up in the terminal. It does work when I flush
explicitly though using `print(..., flush=True)`. This is quite annoying.

The solution is to always flush `stdout` and `stderr` automatically when running
a script. This is done using the CPython API, as just using
`fflush(stdout/stderr)` did not solve the issue.

Pull Request: https://projects.blender.org/blender/blender/pulls/136632
This commit is contained in:
Jacques Lucke
2025-04-01 12:41:38 +02:00
parent e6b89924a0
commit 46fc5cb2cf
3 changed files with 49 additions and 0 deletions

View File

@@ -1687,6 +1687,46 @@ bool PyC_RunString_AsStringOrNone(const char *imports[],
#endif /* #ifndef MATH_STANDALONE */
/* -------------------------------------------------------------------- */
/** \name Std Files Flush
*
* \{ */
void PyC_StdFilesFlush()
{
/* This is ported from CPython's internal #flush_std_files (2025-03-31). The code is a bit
* different because the original code uses some internal APIs.
*
* This is approximately equivalent to:
* ```
* try:
* sys.stdout.flush()
* sys.stderr.flush()
* except Exception:
* pass
* ```
*/
PyObject *py_flush = PyUnicode_FromString("flush");
BLI_assert(py_flush);
for (const char *name : {"stdout", "stderr"}) {
PyObject *py_file = PySys_GetObject(name);
if (!py_file) {
PyErr_Clear();
continue;
}
PyObject *py_flush_retval = PyObject_CallMethodNoArgs(py_file, py_flush);
if (py_flush_retval) {
Py_DECREF(py_flush_retval);
}
else {
PyErr_Clear();
}
}
Py_DECREF(py_flush);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Int Conversion
*

View File

@@ -259,6 +259,11 @@ bool PyC_RunString_AsStringOrNone(const char **imports,
const char *filename,
char **r_value) ATTR_NONNULL(2, 3, 4) ATTR_WARN_UNUSED_RESULT;
/**
* Flush stdout and stderr. Errors are ignored.
*/
void PyC_StdFilesFlush();
/**
* Use with PyArg_ParseTuple's "O&" formatting.
*

View File

@@ -217,6 +217,10 @@ static bool python_script_exec(
PyC_MainModule_Restore(main_mod);
/* Flush stdout/stderr to ensure the script output is visible.
* Using fflush(stdout) does not solve it. */
PyC_StdFilesFlush();
bpy_context_clear(C, &gilstate);
return (py_result != nullptr);