2011-03-23 56 views
10

我需要運行一個程序並將其輸出採集到標準輸出。這個程序(socat)需要在python腳本的後臺運行。 Socatat一旦運行就會處於dameon模式,但首先它會輸出一些行,以便爲我的腳本的其餘部分提供所需的stdout。Python運行守護進程子進程和讀取標準輸出

命令:socat -d -d PTY: PTY:

輸出:

2011/03/23 21:12:35 socat[7476] N PTY is /dev/pts/1 
2011/03/23 21:12:35 socat[7476] N PTY is /dev/pts/2 
2011/03/23 21:12:35 socat[7476] N starting data transfer loop with FDs [3,3] and [5,5] 

...

我基本上要運行,在我的程序的啓動和保持運行狀態,直到腳本結束,但我需要將兩個/ dev/pts/X名稱讀入python。

誰能告訴我如何做到這一點?

我想出了這只是掛起,我猜是因爲它阻止子進程終止。

#!/usr/bin/python 
from subprocess import Popen, PIPE, STDOUT 

cmd = 'socat -d -d PTY: PTY: &' 

p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) 
output = p.stdout.read() 

# Process the output 
print(output) 

感謝所有幫助

編輯:看來,這可能會寫入標準錯誤,但劇本還只是與不&甚至從標準錯誤讀hanges。

+1

沒有'&'嗎? – 2011-03-23 21:28:06

+0

不好(可惜不是,它只是掛起。 – Jason 2011-03-23 21:31:20

+0

您是否嘗試過在打印語句中添加以確認在您調用'Popen'後阻止並在read()'調用上阻塞? – Jeff 2011-03-23 22:26:47

回答

18
#!/usr/bin/python 
from subprocess import Popen, PIPE, STDOUT 
import pty 
import os 

cmd = 'socat -d -d PTY: PTY:' 

master, slave = pty.openpty() 

p = Popen(cmd, shell=True, stdin=PIPE, stdout=slave, stderr=slave, close_fds=True) 
stdout = os.fdopen(master) 
print stdout.readline() 
print stdout.readline() 

您的版本有兩個問題。首先,你在沒有參數的情況下調用read,這意味着它會嘗試讀取所有內容。但由於社會不終止,它從來沒有決定它已經閱讀了所有內容。通過使用readline,python只會讀取直到找到換行符。根據我對你的問題的理解,你需要的是什麼。

第二個問題是C標準庫將在管道上緩衝輸出。我們通過使用openpty()函數創建一個pty並將其傳遞給子進程的stdout和stderr來解決此問題。我們使用fdopen將該文件描述符變成一個常規的python對象,並且我們擺脫了緩衝。

我不知道你在做什麼與socat,但我不知道它是否可以取代使用pty模塊。您正在將一個pty複製到另一個pty,而openpty正在創建一對ptys。也許你可以直接使用它們?

+0

非常感謝,這完美的作品。我會考慮使用內置的pty模塊替換socat。 – Jason 2011-03-24 08:25:48

0

如果你爲stdout和stderr提供一個管道,我認爲子進程會阻塞等待管道讀取。 .read()應該讀取到EOF,我想。在他們之間,這兩個問題很容易導致僵局。

但是,我認爲,由於.read()會讀取直到EOF,即使沒有stderr管道,它也會阻塞。

我想,你想把閱讀插入一個線程中。

1

子進程可能永遠不會關閉標準輸出,因此read()調用將永遠等待。更糟糕的是,它可能會在其輸出緩衝其輸出時發現它是一個管道而不是控制檯(標準C庫自動執行此操作,所以這不是巧妙編寫應用程序的功能)。如果是這樣,可能唯一的選擇是使用預期類型的​​庫,例如Pexpect