Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Controlling C++ Output from Python Script

Tags:

c++

python

I have a bit of an issue here. I have a Python script which calls binaries compiled from C++. The Python script has its own set of outputs (to standard out and error), which are easily disable-able. The C++ binaries have their own set of outputs (to standard out and error, among others) as well; the source can be altered, but I am not the original author. This is an issue because I do not want the C++ output in my final program, and I also don't want future users to need to edit the C++ source.

What I'd like to be able to do is have some Python method which will catch the C++ code's output that is sent to standard out or error. Is this possible? If so, could someone point me in the right direction?

Thank you!!

like image 923
learner Avatar asked Mar 08 '26 23:03

learner


1 Answers

One way to do this is:

  • Duplicate in python the file descriptors for stdout and stderr using os.dup.
  • Redirect the original stdout and stderr using reopen (from C's stdio) to write to a file of your choice.

Note: reopen isn't available directly from python, but you should be able to call it as in the example below or using any other wrapper available.

After this is done:

  • Every write to cout and cerr in C++ will write to the output files.
  • Every print statement in python will write to the output files.

However, since the original descriptors are duplicated, you can still (see example below):

  • Print to the original stdout/stderr using sdout.write and stdout.err
  • Use logging methods after configuring properly the stream parameter

The following code uses instant library to test real C++ code that is wrapped into python using SWIG and that should be similar to the library that you have:

import sys, os
import logging
from instant import inline

print 'This is printed from python to stdout'
stdout = os.fdopen(os.dup(sys.stdout.fileno()), 'w')
stderr = os.fdopen(os.dup(sys.stderr.fileno()), 'w')

logging.basicConfig(stream=stderr, level=logging.DEBUG)

redirect = inline("""                                                                                                                    
void redirect(void) {                                                                                                                    
    freopen("my_stdout.txt", "w", stdout);                                                                                               
    freopen("my_stderr.txt", "w", stderr);                                                                                               
}                                                                                                                                        
""")
redirect()

cout = inline("""                                                                                                                        
void cout(void) {                                                                                                                        
    std::cout << "This is written from C++ to my_stdout.txt" << std::endl;                                                               
    std::cerr << "This is written from C++ to my_stderr.txt" << std::endl;                                                               
}                                                                                                                                        
""")
cout()

print 'This is written from python to my_stdout.txt'

stdout.write('This is printed from python to stdout\n')
stderr.write('This is printed from python to stderr\n')
logging.info('This is printed to stderr from python using logging')

The output for this example is:

$ python test.py
This is printed from python to stdout
This is printed from python to stdout
This is printed from python to stderr
INFO:root:This is printed to stderr from python using logging
$ cat my_stdout.txt 
This is written from C++ to my_stdout.txt
This is written from python to my_stdout.txt
$ cat my_stderr.txt 
This is written from C++ to my_stderr.txt

Note: First time the code is executed, you might get gcc compilation messages (I've removed them to make the example clearer).

like image 102
jcollado Avatar answered Mar 10 '26 12:03

jcollado



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!