通过Python脚本控制C++输出
我遇到了一点问题。我有一个Python脚本,它会调用一些用C++编写的程序。这个Python脚本有自己的输出(包括正常输出和错误输出),这些输出是可以轻松关闭的。而那些C++程序也有自己的输出(同样是正常输出和错误输出等),虽然我可以修改源代码,但我并不是原作者。这就成了一个问题,因为我不想在我的最终程序中看到C++的输出,也不希望将来的用户需要去修改C++的源代码。
我希望能有一个Python的方法,可以捕捉到C++代码发送到正常输出或错误输出的内容。这样做可能吗?如果可以的话,有人能给我指个方向吗?
谢谢!!
2 个回答
0
你是在用 subprocess
来编译 C++ 吗?如果是的话,你可以设置错误信息和正常输出信息的去向:
nowhere = StringIO()
subprocess.call("exit 1", shell=True, stdout=nowhere, stderr=nowhere)
8
实现这个功能的一种方法是:
- 在 Python 中使用
os.dup
复制stdout
和stderr
的文件描述符。 - 使用
reopen
(来自 C 的stdio
)重定向原来的stdout
和stderr
,让它们写入你选择的文件。
注意:reopen
在 Python 中不能直接使用,但你可以像下面的例子那样调用它,或者使用其他可用的封装。
完成这些后:
- C++ 中每次写入
cout
和cerr
都会写入输出文件。 - Python 中每个
print
语句都会写入输出文件。
不过,由于原始的描述符被复制了,你仍然可以(见下面的例子):
- 使用
sdout.write
和stdout.err
打印到原始的stdout
/stderr
- 在正确配置
stream
参数后使用logging
方法
下面的代码使用 instant 库来测试真实的 C++ 代码,这些代码通过 SWIG 封装到 Python 中,应该和你拥有的库类似:
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')
这个例子的输出是:
$ 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
注意:第一次执行代码时,你可能会看到 gcc
的编译信息(我已经把它们去掉了,以便让例子更清晰)。