用python从c模块捕获打印输出

用python从c模块捕获打印输出,python,c,printing,binding,output,Python,C,Printing,Binding,Output,我想将pycosat的这个详细输出存储到一个字符串中: import pycosat cnf = [[1, -5, 4], [-1, 5, 3, 4], [-3, -4]] pycosat.solve(cnf,verbose=5) 我找到了各种各样的解决办法。 但是,基于stringIO()的解决方案不会捕获pycosat输出。输出正常打印,并捕获空字符串 我认为这与pycosat是c库picosat的绑定有关,但我不知道如何处理这个问题 这个解决方案也不起作用 巨蟒将冻结在 out.st

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

import pycosat
cnf = [[1, -5, 4], [-1, 5, 3, 4], [-3, -4]]
pycosat.solve(cnf,verbose=5)
我找到了各种各样的解决办法。

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

我认为这与pycosat是c库picosat的绑定有关,但我不知道如何处理这个问题

这个解决方案也不起作用

巨蟒将冻结在

out.stop()
sys.stdout = StringIO()
ipython也将在晚上冻结

out.stop()
sys.stdout = StringIO()
这可能与此有关

我没有尝试使用使用subprocess的解决方案,因为我需要局部变量cnf,并且将其传递到subprocess中没有意义


我不知道它是否相关,但我正在osx-64上使用conda 3.14.1,有时可能会出现问题,因为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正在使用另一个filedescriptor作为其输出(既不是标准输出,也不是标准输出),您将不得不手动连接到它。

这里找到的子流程解决方案确实有效

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字符串),但至少它可以工作。

您确实在Mac OS X内置Python上尝试过它,对吗?我没有,因为我没有在那里安装pycosat(由于包问题,我使用conda),不幸的是,这也没有捕获输出。您建议我手动连接到它。你的意思是我必须编辑绑定吗?在我看来,c文件中使用标准输出来打印您在使用标准输出处理块时所说的结果。所以它可能确实使用标准输出,但它通过FCNTL对终端进行了一些更改。因此,StringIO()不是一个无法应用的终端,它会阻塞。在这种情况下,您应该能够通过在sys.stdout中放入一些伪终端来愚弄pycosat。请参阅模块tty。它将在一端写入,您将从另一端读取。通过-手动-我的意思是,如果使用的另一个文件描述符不是sys.stdout或sys.stderr,而是桥接到它们,您将能够使用os.fdopen()包装它,然后以某种方式重定向它。但开放新的终端并不常见。要查看是否创建了任何其他tty,请在导入pycosat后查看所有打开的文件。命令lsof在Linux上,我现在没有在Mac上启动检查,也许是一样的。