通过Python脚本控制C++输出

3 投票
2 回答
3760 浏览
提问于 2025-04-17 08:20

我遇到了一点问题。我有一个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 复制 stdoutstderr 的文件描述符。
  • 使用 reopen(来自 C 的 stdio)重定向原来的 stdoutstderr,让它们写入你选择的文件。

注意:reopen 在 Python 中不能直接使用,但你可以像下面的例子那样调用它,或者使用其他可用的封装。

完成这些后:

  • C++ 中每次写入 coutcerr 都会写入输出文件。
  • Python 中每个 print 语句都会写入输出文件。

不过,由于原始的描述符被复制了,你仍然可以(见下面的例子):

  • 使用 sdout.writestdout.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 的编译信息(我已经把它们去掉了,以便让例子更清晰)。

撰写回答