2014-02-26 41 views
2

我想通過stdout將一個執行的命令與subprocess.Popen()一起記錄到UDP套接字。我在網上看到過嘗試,但至少在我的情況下沒有真正的成功。如何從subprocess.Popen調用stdout.write?

有些人試圖對套接字進行子類化並將其傳遞給Popen的「stdout」參數,以覆蓋通過套接字發送的默認.write方法。 http://www.dreamincode.net/forums/topic/209734-using-a-socket-as-stdinstdout/

我也嘗試繼承「文件」類並覆蓋寫入方法與我的實現,但Popen似乎並沒有調用任何寫入方法。

事實上,這個子類化的想法不能用於Popen(args,stdout = mysocket)不調用任何mysocket.write(或任何.write)方法的簡單原因。爲了測試這個,我在調試模式下調用了Popen,並試圖從其init到最後沒有找到任何.write或類似的東西。我正在使用python 2.7

當然我知道我可以發送stdout到PIPE然後讀取它,但是這需要在我的情況下創建(多於一個)工作線程來讀取PIPE併發送,並且如果可能的話我想避免這個解決方案,如果更簡單的一個可用較低的努力。

我的文件子

class Foo(file): 
    dbgIP = "" 
    dbgPORT = 0 
    sck = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) 

    def __init__(self, dbgIP, dbgPORT): 
     file.__init__(self,"empty",'w') 
     self.sck.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) 
     self.dbgIP = dbgIP 
     self.dbgPORT = dbgPORT 

    def write(self, text): 
     return self.sck.sendto(text, (self.dbgIP, self.dbgPORT)) 

的示例調用

foofile = Foo(MCAST_GROUP,MCAST_PORT) 
subprocess.Popen("jackd -R -P62 -dalsa -dhw:0 -p256 -n2 -i2 -o2 -s -S -r22050",shell=True, stdout=foofile, stderr=subprocess.STDOUT) 

調用foofile.write("asd")優良工程

+0

您是否試圖在'Foo.write'中插入print語句來確保它不被調用? –

+0

是的,雙重檢查,類是正確實例化(在構造函數的末尾用打印檢查),套接字工作(如果調用'foofile.write(「asd」)',但寫入永遠不會被Popen調用並因此沒有控制檯打印出現,因爲你建議) –

+0

是否Popen實現更改及時?我正在運行Python 2.7.5 + –

回答

0

Popen()作品在文件描述符(處理)的水平。這意味着子類化和重寫.write()方法將不起作用。在一些系統中real socket (valid .fileno()) can be passed to stdout as is

from subprocess import call, STDOUT 

rc = call("./generate-output", stdout=sck, stderr=STDOUT) 

在其他系統上,你可以自己動手完成它:

import shutil 
from subprocess import Popen, PIPE, STDOUT 

p = Popen("./generate-output", stdout=PIPE, stderr=STDOUT, bufsize=-1) 
shutil.copyfileobj(p.stdout, foofile) 
p.stdout.close() 
rc = p.wait() 

在更一般的情況下,可以使用類似的東西teed_call()


1)插座爲標準輸出,如何確定哪些系統將工作的使用情況如何?它取決於Unix風格/ Win還是Python版本?

我已經在Linux上試過了。我期望它可以在POSIX系統上工作。

2)如果我想插座的子類,我應該修改哪些方法,例如,添加一個字符串到來自標準輸出的字符串?

在這種情況下,您不應該繼承套接字。 .fileno()是由subprocess調用的唯一方法。 「在文件描述符級別工作」意味着一旦你給文件描述符並且發生重定向,剩下的就是內核業務。

3)我假設copyfileobj的代碼將啓動從標準輸出到foofile的複製,直到進程處於活動狀態。但是,關閉標準輸出不會阻止進程和foofile之間的通信? -

copyfileobj()複製到EOF的p.stdoutIt is pure Python

def copyfileobj(fsrc, fdst, length=16*1024): 
    """copy data from file-like object fsrc to file-like object fdst""" 
    while 1: 
     buf = fsrc.read(length) 
     if not buf: 
      break 
     fdst.write(buf) 

p.stdout.close()被調用以避免泄漏的文件描述符(清理)。

存在一個緩衝區,因此在子進程終止後仍可能發生複製。並且因爲子進程在它仍然活着的時候可能會關閉它的stdout。

+0

謝謝所有這些選項都聽起來不錯,我有幾個問題: 1.使用套接字作爲stdout,如何確定哪些系統可以工作?發現Unix的味道/贏,或蟒蛇版本? 2.如果我想要插座的子類,我應該修改哪些方法,例如添加一個字符串到來自標準輸出的字符串? 3.我假設copyfileobj的代碼將啓動從stdout到foofile的複製,直到進程處於活動狀態。但是,關閉標準輸出不會阻止進程和foofile之間的通信? –

+0

@KeinReverbLeonardoGabrielli:我已經回答了您的意見中的問題 – jfs

+1

謝謝,作爲一個便箋,您提供的第一種方法只能在面向連接的套接字上工作,因爲在給套接字時必須知道目標POPEN。 –

相關問題