Skip to content

Commit f96741e

Browse files
jcfrusiems
authored andcommitted
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 de50aad commit f96741e

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
@@ -1871,18 +1871,22 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ
18711871
PythonQtObjectPtr sys;
18721872
sys.setNewRef(PyImport_ImportModule("sys"));
18731873

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

18871891
// add PythonQt to the list of builtin module names
18881892
PyObject *old_module_names = PyObject_GetAttrString(sys.object(),"builtin_module_names");
@@ -1908,6 +1912,42 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ
19081912
#endif
19091913
}
19101914

1915+
bool PythonQt::redirectStdOutCallbackEnabled() const
1916+
{
1917+
PythonQtObjectPtr sys;
1918+
sys.setNewRef(PyImport_ImportModule("sys"));
1919+
1920+
PythonQtObjectPtr pythonqt_stdout;
1921+
pythonqt_stdout.setNewRef(PyObject_GetAttrString(sys.object(), "pythonqt_stdout"));
1922+
1923+
PythonQtObjectPtr stdout;
1924+
stdout.setNewRef(PyObject_GetAttrString(sys.object(), "stdout"));
1925+
1926+
return PyObject_RichCompareBool(pythonqt_stdout.object(), stdout.object(), Py_EQ);
1927+
}
1928+
1929+
void PythonQt::setRedirectStdOutCallbackEnabled(bool enabled)
1930+
{
1931+
PythonQtObjectPtr sys;
1932+
sys.setNewRef(PyImport_ImportModule("sys"));
1933+
1934+
if (enabled) {
1935+
if( PyObject_HasAttrString(sys.object(), "pythonqt_stdout") ) {
1936+
PyModule_AddObject(sys.object(), "stdout", PyObject_GetAttrString(sys.object(), "pythonqt_stdout"));
1937+
}
1938+
if( PyObject_HasAttrString(sys.object(), "pythonqt_stderr") ) {
1939+
PyModule_AddObject(sys.object(), "stderr", PyObject_GetAttrString(sys.object(), "pythonqt_stderr"));
1940+
}
1941+
} else {
1942+
if( PyObject_HasAttrString(sys.object(), "pythonqt_original_stdout") ) {
1943+
PyModule_AddObject(sys.object(), "stdout", PyObject_GetAttrString(sys.object(), "pythonqt_original_stdout"));
1944+
}
1945+
if( PyObject_HasAttrString(sys.object(), "pythonqt_original_stderr") ) {
1946+
PyModule_AddObject(sys.object(), "stderr", PyObject_GetAttrString(sys.object(), "pythonqt_original_stderr"));
1947+
}
1948+
}
1949+
}
1950+
19111951
QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString& name)
19121952
{
19131953
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)