当前位置: 首页 > 面试题库 >

在python中,如何从c ++共享库捕获标准输出到变量

拓拔富
2023-03-14
问题内容

由于某些其他原因,我使用的c ++共享库将一些文本输出到标准输出。在python中,我想捕获输出并 保存到一个变量中
。关于重定向标准输出,还有许多类似的问题,但在我的代码中不起作用。

1 import sys
2 import cStringIO
3 save_stdout = sys.stdout
4 sys.stdout = cStringIO.StringIO()
5 func()
6 sys.stdout = save_stdout

在第5行中, func() 将调用共享库,共享库生成的文本仍输出到控制台!如果将 func() 更改 为print“ hello”
,则可以使用!

我的问题是:

  1. 如何将c ++共享库的stdout捕获 到变量中
  2. 为什么使用StringIO无法捕获共享库的输出?

问题答案:

Python的sys.stdout对象只是位于普通stdout文件描述符之上的Python包装器-
对其进行更改只会影响Python进程,而不会影响基础文件描述符。任何非Python代码,无论是execed的另一个可执行文件还是已加载的C共享库,都将无法理解,并将继续使用普通的文件描述符进行I
/ O。

因此,为了使共享库输出到其他位置,您需要通过打开一个新的文件描述符,然后使用来替换stdout来更改基础文件描述符os.dup2()。您可以使用临时文件作为输出,但是最好使用使用创建的管道os.pipe()。但是,如果没有任何内容读取管道,则存在死锁的危险,因此为了防止我们可以使用其他线程排空管道。

以下是一个完整的工作示例,该示例不使用临时文件,并且不容易死锁(在Mac OS X上进行了测试)。

C共享库代码:

// test.c
#include <stdio.h>

void hello(void)
{
  printf("Hello, world!\n");
}

编译为:

$ clang test.c -shared -fPIC -o libtest.dylib

Python驱动程序:

import ctypes
import os
import sys
import threading

print 'Start'

liba = ctypes.cdll.LoadLibrary('libtest.dylib')

# Create pipe and dup2() the write end of it on top of stdout, saving a copy
# of the old stdout
stdout_fileno = sys.stdout.fileno()
stdout_save = os.dup(stdout_fileno)
stdout_pipe = os.pipe()
os.dup2(stdout_pipe[1], stdout_fileno)
os.close(stdout_pipe[1])

captured_stdout = ''
def drain_pipe():
    global captured_stdout
    while True:
        data = os.read(stdout_pipe[0], 1024)
        if not data:
            break
        captured_stdout += data

t = threading.Thread(target=drain_pipe)
t.start()

liba.hello()  # Call into the shared library

# Close the write end of the pipe to unblock the reader thread and trigger it
# to exit
os.close(stdout_fileno)
t.join()

# Clean up the pipe and restore the original stdout
os.close(stdout_pipe[0])
os.dup2(stdout_save, stdout_fileno)
os.close(stdout_save)

print 'Captured stdout:\n%s' % captured_stdout


 类似资料:
  • 问题内容: 我正在使用对对象执行某些操作的Python库 并更改它。这样做时,它会向stdout打印一些统计信息,我希望掌握这些信息。正确的解决方案是更改以返回相关信息, 但是开发人员需要一段时间才能解决此问题。作为一种解决方法,我考虑过解析对stdout的任何写入。 如何捕获代码中两点之间的stdout输出,例如 ? 问题答案: 试试这个上下文管理器: 用法: 现在是一个包含函数调用打印的行的列

  • 问题内容: 我正在生成大量的XML,当用户单击表单按钮时,这些XML将作为发布变量传递到API。我还希望能够事先向用户显示XML。 该代码有点像以下结构: 我的XML正在生成一些while循环和其他内容。然后需要在两个位置(预览和表单值)中显示它。 我的问题是。我如何在变量中捕获生成的XML或其他内容,所以我只需要生成一次,然后将其打印出来就可以在预览中生成,然后在表单值中生成? 问题答案:

  • 问题内容: 我试图用Python编写程序,并被告知运行.exe文件。运行此.exe文件时,它会吐出大量数据,并且我需要在屏幕上打印出一定的行。我很确定我需要使用或类似的东西,但是我是子处理的新手,没有任何线索。有人有简单的方法让我完成此工作吗? 问题答案: 像这样:

  • 问题内容: 我想在Windows中使用rsync.exe,并在Python中打印标准输出。 我的代码可以运行,但是直到文件传输完成后才能捕获进度!我想实时打印每个文件的进度。 既然我听说使用Python 3.1,现在应该会更好地处理IO。 问题答案: 一些经验法则。 永远不要使用。它不必要地调用额外的shell进程来调用您的程序。 调用进程时,参数作为列表传递。sys.argv在python中是一

  • 问题内容: 例如,在Python中,我可以执行以下操作: 您可以在Go中执行此操作吗? 问题答案: 我同意,只要可以管理,就应该使用这些功能。但是,如果您不控制要捕获其输出的代码,则可能没有该选项。 Mostafa的答案有效,但是如果您想在没有临时文件的情况下进行操作,则可以使用os.Pipe。这是一个与Mostafa等效的示例,其中一些代码受Go的测试包的启发。

  • 问题内容: 我正在尝试从Python内部进行比特币付款。在bash中,我通常会这样做: 因此,例如: 如果成功,我会得到一个交易ID作为输出,但是如果我尝试转账大于我的比特币余额的金额,则会得到以下输出: 现在,在我的Python程序中,我尝试按以下方式进行付款: 如果有足够的余额,则可以正常工作,但是如果没有足够的余额,则会输出以下内容: 它不包括我在命令行中得到的错误。所以我的问题是;如何从P