【问题标题】:Capture print output from a c-module in python从python中的c模块捕获打印输出
【发布时间】:2015-10-19 11:09:57
【问题描述】:

我想将 pycosat 的详细输出存储到一个字符串中:

import pycosat
cnf = [[1, -5, 4], [-1, 5, 3, 4], [-3, -4]]
pycosat.solve(cnf,verbose=5)

我找到了各种解决方案,例如 Capture stdout from a script in Python

但是,基于 stringIO() 的解决方案不会捕获 pycosat 输出。输出正常打印,并捕获一个空字符串。

我认为这与 pycosat 绑定到 c-library picosat 的事实有关,但我不知道如何处理。

此解决方案也不起作用 https://stackoverflow.com/a/29834357/4270148

Python 将冻结在

out.stop()

ipython 也会冻结在

sys.stdout = StringIO()

这可能与它有关。

我没有尝试使用使用子进程的解决方案,因为我需要局部变量cnf,将它传递给子进程并没有什么意义。

我不知道它是否应该相关,但我在 osx-64 上使用 conda 3.14.1

【问题讨论】:

  • 你确实在 Mac OS X 内置的 Python 上试过了,对吧?
  • 我没有,因为我没有在那里安装 pycosat(由于包问题我使用 conda)

标签: python c printing binding output


【解决方案1】:

在这里找到的子流程解决方案https://stackoverflow.com/a/5136686/4270148,确实有效!

import subprocess
proc = subprocess.Popen(["python", "-c",
    "cnf = [[1, -5, 4], [-1, 5, 3, 4], [-3, -4]];\
    import pycosat;\
    pycosat.solve(cnf,verbose=5);"],
    stdout=subprocess.PIPE)
out = proc.communicate()[0]

我不喜欢程序的传递方式(作为 eval 字符串),但至少它可以工作。

【讨论】:

    【解决方案2】:

    有时这可能是个问题,因为 Mac OS 只有虚拟终端,而真正的控制台是隐藏的。所以 stdout 和 stderr 有时会表现得很奇怪。 (非常罕见的情况)

    尝试使用 stderr:

    from cStringIO import StringIO
    import sys
    import pycosat
    cnf = [[1, -5, 4], [-1, 5, 3, 4], [-3, -4]]
    sys.stderr = StringIO()
    pycosat.solve(cnf,verbose=5)
    solution = sys.stderr.getvalue()
    sys.stderr = sys.__stderr__
    print solution
    

    如果这仍然对您没有好处,那么 pycosat 正在使用另一个文件描述符作为其输出(既不是 stdout 也不是 stder),您必须手动连接到它。

    【讨论】:

    • 不幸的是,这也没有捕获输出。你建议我手动连接它。您的意思是说我必须编辑绑定吗?在我看来,c文件中使用了stdout来打印结果github.com/ContinuumIO/pycosat/blob/master/picosat.c#L1216github.com/ContinuumIO/pycosat/blob/master/picosat.c#L3499
    • 您在使用 stdout 进程块时说过。因此,它可能确实使用了标准输出,但它通过 FCNTL 对终端进行了一些更改。所以 StringIO() 不是一个不能应用的终端,也不是事物阻塞的终端。在这种情况下,您应该能够通过将一些伪终端放入 sys.stdout 来欺骗 pycosat。请参阅模块 tty。它会在一端写入,而您将从另一端读取它。
    • 通过-manually-我的意思是,如果使用另一个不是sys.stdout 也不是sys.stderr 的文件描述符,但它被桥接到它们,您可以使用os.fdopen( ),然后以某种方式重定向它。但开设新航站楼并不常见。要查看是否创建了任何其他 tty,请查看导入 pycosat 后所有打开的文件。 Linux 上的命令 lsof,我现在没有在 Mac 上启动检查,也许是一样的。
    猜你喜欢
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 2023-02-21
    相关资源
    最近更新 更多