Skip to content

Commit f630bc9

Browse files
committed
Add support for enabling stdout/stderr redirection
This improves the PythonQt module by adding functionality to redirect stdout and stderr to custom callbacks. It includes methods to enable or disable redirection and to check if redirection is currently enabled. (cherry picked from commit commontk/PythonQt@3d3943f)
1 parent 3eed19c commit f630bc9

File tree

2 files changed

+64
-12
lines changed

2 files changed

+64
-12
lines changed

src/PythonQt.cpp

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,18 +1864,22 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ
18641864
PythonQtObjectPtr sys;
18651865
sys.setNewRef(PyImport_ImportModule("sys"));
18661866

1867-
if (redirectStdOut) {
1868-
PythonQtObjectPtr out;
1869-
PythonQtObjectPtr err;
1870-
// create a redirection object for stdout and stderr
1871-
out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,nullptr, nullptr);
1872-
((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1873-
err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,nullptr, nullptr);
1874-
((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1875-
// replace the built in file objects with our own objects
1876-
PyModule_AddObject(sys, "stdout", out);
1877-
PyModule_AddObject(sys, "stderr", err);
1878-
}
1867+
// Backup original 'sys.stdout' and 'sys.stderr'
1868+
PyModule_AddObject(sys, "pythonqt_original_stdout", PyObject_GetAttrString(sys, "stdout"));
1869+
PyModule_AddObject(sys, "pythonqt_original_stderr", PyObject_GetAttrString(sys, "stderr"));
1870+
1871+
// Create a redirection object for stdout and stderr
1872+
PythonQtObjectPtr out;
1873+
PythonQtObjectPtr err;
1874+
out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1875+
((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1876+
err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1877+
((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1878+
// replace the built in file objects with our own objects
1879+
PyModule_AddObject(sys, "pythonqt_stdout", out);
1880+
PyModule_AddObject(sys, "pythonqt_stderr", err);
1881+
1882+
setRedirectStdOutCallbackEnabled(redirectStdOut);
18791883

18801884
// add PythonQt to the list of builtin module names
18811885
PyObject *old_module_names = PyObject_GetAttrString(sys.object(),"builtin_module_names");
@@ -1901,6 +1905,42 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ
19011905
#endif
19021906
}
19031907

1908+
bool PythonQt::redirectStdOutCallbackEnabled() const
1909+
{
1910+
PythonQtObjectPtr sys;
1911+
sys.setNewRef(PyImport_ImportModule("sys"));
1912+
1913+
PythonQtObjectPtr pythonqt_stdout;
1914+
pythonqt_stdout.setNewRef(PyObject_GetAttrString(sys.object(), "pythonqt_stdout"));
1915+
1916+
PythonQtObjectPtr stdout;
1917+
stdout.setNewRef(PyObject_GetAttrString(sys.object(), "stdout"));
1918+
1919+
return PyObject_RichCompareBool(pythonqt_stdout.object(), stdout.object(), Py_EQ);
1920+
}
1921+
1922+
void PythonQt::setRedirectStdOutCallbackEnabled(bool enabled)
1923+
{
1924+
PythonQtObjectPtr sys;
1925+
sys.setNewRef(PyImport_ImportModule("sys"));
1926+
1927+
if (enabled) {
1928+
if( PyObject_HasAttrString(sys.object(), "pythonqt_stdout") ) {
1929+
PyModule_AddObject(sys.object(), "stdout", PyObject_GetAttrString(sys.object(), "pythonqt_stdout"));
1930+
}
1931+
if( PyObject_HasAttrString(sys.object(), "pythonqt_stderr") ) {
1932+
PyModule_AddObject(sys.object(), "stderr", PyObject_GetAttrString(sys.object(), "pythonqt_stderr"));
1933+
}
1934+
} else {
1935+
if( PyObject_HasAttrString(sys.object(), "pythonqt_original_stdout") ) {
1936+
PyModule_AddObject(sys.object(), "stdout", PyObject_GetAttrString(sys.object(), "pythonqt_original_stdout"));
1937+
}
1938+
if( PyObject_HasAttrString(sys.object(), "pythonqt_original_stderr") ) {
1939+
PyModule_AddObject(sys.object(), "stderr", PyObject_GetAttrString(sys.object(), "pythonqt_original_stderr"));
1940+
}
1941+
}
1942+
}
1943+
19041944
QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString& name)
19051945
{
19061946
QStringList tmp = name.split(".");

src/PythonQt.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,18 @@ class PYTHONQT_EXPORT PythonQt : public QObject {
268268

269269
//@}
270270

271+
//---------------------------------------------------------------------------
272+
//! \name Standard output handling
273+
//@{
274+
275+
//! return \a true if std out/err redirection is enabled.
276+
bool redirectStdOutCallbackEnabled() const;
277+
278+
//! enable or disable std out/err redirection to pythonStdOut() and pythonStdErr() signals.
279+
void setRedirectStdOutCallbackEnabled(bool enabled);
280+
281+
//@}
282+
271283
//---------------------------------------------------------------------------
272284
//! \name Modules
273285
//@{

0 commit comments

Comments
 (0)