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

Discussion in 'Python' started by Utpal Sarkar, Jan 17, 2013.

  1. Utpal Sarkar

    Utpal Sarkar Guest

    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.
    Utpal Sarkar, Jan 17, 2013
    #1
    1. Advertising

  2. Utpal Sarkar

    Nobody Guest

    On Thu, 17 Jan 2013 07:02:24 -0800, Utpal Sarkar wrote:

    > 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().
    Nobody, Jan 17, 2013
    #2
    1. Advertising

  3. On Fri, Jan 18, 2013 at 2:02 AM, Utpal Sarkar <> wrote:
    > 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
    Chris Angelico, Jan 17, 2013
    #3
  4. Utpal Sarkar

    Utpal Sarkar Guest

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

    > > 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
    Utpal Sarkar, Jan 17, 2013
    #4
  5. Utpal Sarkar

    Utpal Sarkar Guest

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

    > > 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
    Utpal Sarkar, Jan 17, 2013
    #5
  6. On Fri, Jan 18, 2013 at 2:51 AM, Utpal Sarkar <> wrote:
    > 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
    Chris Angelico, Jan 17, 2013
    #6
  7. Utpal Sarkar

    Lie Ryan Guest

    On 18/01/13 02:02, Utpal Sarkar wrote:
    > 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.
    Lie Ryan, Jan 18, 2013
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roman Neuhauser
    Replies:
    0
    Views:
    643
    Roman Neuhauser
    Apr 4, 2005
  2. Replies:
    2
    Views:
    637
    velle
    Jan 5, 2006
  3. Replies:
    0
    Views:
    446
  4. Michel Albert
    Replies:
    5
    Views:
    1,352
    Daniel Dehennin
    Oct 24, 2012
  5. Geoff Bache
    Replies:
    4
    Views:
    530
Loading...

Share This Page