python sys.stdout and C++ iostreams::cout

U

Utpal Sarkar

Hi,

I was assuming that sys.stdout would be referencing the same physical stream as iostreams::cout running in the same process, but this doesn't seem to be the case.
The following code, which makes a call to a C++ function with a python wrapper called "write", that writes to cout:

from cStringIO import StringIO
import sys
orig_stdout = sys.stdout
sys.stdout = stringout = StringIO()
write("cout") # wrapped C++ function that writes to cout
print "-" * 40
print "stdout"
sys.stdout = orig_stdout
print stringout.getvalue()

immediately writes "cout" to the console, then the separator "---...", and finally, as the return value of stringout.getvalue(), the string "stdout".
My intention was to capture in stringout also the string written to cout from C++.
Does anyone know what is going on, and if so, how I can capture what is written to cout in a python string?

Thanks in advance.
 
N

Nobody

I was assuming that sys.stdout would be referencing the same physical
stream as iostreams::cout running in the same process, but this doesn't
seem to be the case.

At startup, it refers to the same FILE* as C's stdout. This initially
shares a buffer with C++'s std::cout, but that can be changed via
std::ios_base::sync_with_stdio().

However ...
The following code, which makes a call to a C++
function with a python wrapper called "write", that writes to cout:

from cStringIO import StringIO
import sys
orig_stdout = sys.stdout
sys.stdout = stringout = StringIO()
write("cout") # wrapped C++ function that writes to cout print "-" * 40
print "stdout"
sys.stdout = orig_stdout
print stringout.getvalue()

This code changes sys.stdout so that it refers to something other than C's
stdout. C's stdout is still the same FILE*, C++'s std::count is still the
same std::eek:stream, and the synchronisation between the two hasn't changed.
immediately writes "cout" to the console, then the separator "---...", and
finally, as the return value of stringout.getvalue(), the string "stdout".
My intention was to capture in stringout also the string written to cout
from C++. Does anyone know what is going on, and if so, how I can capture
what is written to cout in a python string?

Changing sys.stdout doesn't (and cannot) have any effect upon how C or C++
code behaves. sys.stdout is just a Python variable.

If you want to capture output from C or C++ code, you'll have to do so via
other means, e.g. freopen() or dup2().
 
C

Chris Angelico

I was assuming that sys.stdout would be referencing the same physical stream as iostreams::cout running in the same process, but this doesn't seem to be the case.

That's more-or-less true, but there will likely be separate buffering,
so even without redirection you might see some oddities. But the
problem with your code is that you're not actually redirecting stdout
in any way; you're catching, at a fairly high level, everything that
Python would otherwise have sent there.

Is there any way that you can get the C++ code to offer a way to
redirect its output? Otherwise, you're going to have to fiddle around
with the usual mess of I/O redirection (with dup2), and you can only
send it to what the OS sees as a file (so, no StringIO buffer). So to
achieve your goal, you may need either a temporary physical file, or
some sort of pipe (and worry about reading from it before it fills up,
etc, etc). There may be alternatives, but in any case, the easiest way
is going to be with some assistance from the C++ function.

ChrisA
 
C

Chris Angelico

Thanks a lot Chris and Nobody! I'll have a look at dup2 for a start.

Okay. Look for code that redirects the standard I/O streams and then
exec()s another process (possibly after fork()ing); you're going to be
doing pretty much the same thing. Good luck, have fun. It's a LOT
messier than simply assigning to sys.stdout, unfortunately.

ChrisA
 
L

Lie Ryan

Hi,

I was assuming that sys.stdout would be referencing the same physical stream as iostreams::cout running in the same process, but this doesn't seem to be the case.
The following code, which makes a call to a C++ function with a python wrapper called "write", that writes to cout:

from cStringIO import StringIO
import sys
orig_stdout = sys.stdout
sys.stdout = stringout = StringIO()
write("cout") # wrapped C++ function that writes to cout
print "-" * 40
print "stdout"
sys.stdout = orig_stdout
print stringout.getvalue()

immediately writes "cout" to the console, then the separator "---...", and finally, as the return value of stringout.getvalue(), the string "stdout".
My intention was to capture in stringout also the string written to cout from C++.
Does anyone know what is going on, and if so, how I can capture what is written to cout in a python string?

Thanks in advance.

You might have a better luck if you check std::ios::rdbuf
(http://www.cplusplus.com/reference/ios/ios/rdbuf/)

Using std::ios::rdbuf() you can get the cout's streambuf, which is a
filebuf for the stdout and then use std::ios::rdbuf(streambuf*) to
replace cout's internal streambuf and replace it with your own
implementation that captures everything written using cout before
passing it back to the original streambuf.

This is essentially similar to assigning to sys.stdout in python.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top