2015-10-19 86 views
2

我想pycosat的这个详细的输出存储到字符串:捕获输出打印在python

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库picosat的事实有关,但我不知道如何处理这个问题。

该解决方案无法正常工作或 https://stackoverflow.com/a/29834357/4270148

Python会在

out.stop() 

冻结IPython中也将冻结在

sys.stdout = StringIO() 

可能有事情做吧。

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

我不知道这是否应该是相关的,但我使用OSX-64

+0

你确实在Mac OS X内建的Python上尝试过它,对不对? – Dalen

+0

我没有,因为我没有安装pycosat(我使用conda,因为包问题) – Tivaro

回答

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

0

有时畅达3.14.1它可以是一个问题,因为Mac OS提供了唯一的虚拟终端,而真正的控制台被隐藏。所以stdout和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使用另一个文件描述符其输出(既不是标准输出也不stder),你将不得不连接手动。

+0

不幸的是,这并不捕获输出。 你建议我手动连接它。这是否意味着我将不得不编辑绑定? 在我看来,在c文件中使用stdout来打印结果 https://github.com/ContinuumIO/pycosat/blob/master/picosat.c#L1216 https://github.com/ ContinuumIO/pycosat/blob/master/picosat.c#L3499 – Tivaro

+0

你说过使用stdout进程块的时候。所以它可能会使用stdout,但它会通过FCNTL对终端进行一些更改。因此,由于StringIO()不是无法应用和终止的终端。在这种情况下,你应该可以通过将伪终端放入sys.stdout来愚弄pycosat。请参阅模块tty。它会在一端写上它,然后你会从另一端读取它。 – Dalen

+0

通过手动 - 我的意思是,如果使用另一个不是sys.stdout和sys.stderr的filedescriptor,但是它被桥接到它们,你可以使用os.fdopen()来包装它,然后将它重定向到某种方式。但是打开新的终端并不常见。要查看是否创建了任何其他tty,请在导入pycosat后查看所有打开的文件。在Linux上的命令lsof,我现在不在Mac引导来检查,也许是一样的。 – Dalen