2015-10-19 120 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