2010-04-28 54 views
6

我有一個從stdin讀取的命令行工具。 在命令行中我要麼運行...我可以在Python中使用Popen打開的gzip文件嗎?

./foo < bar 

或...

cat bar | ./foo 

隨着gziped文件,我可以在Python運行

zcat bar.gz | ./foo 

我能做到。 ..

Popen(["./foo", ], stdin=open('bar'), stdout=PIPE, stderr=PIPE) 

但我不能做

import gzip 
Popen(["./foo", ], stdin=gzip.open('bar'), stdout=PIPE, stderr=PIPE) 

我拉閘不必運行

p0 = Popen(["zcat", "bar"], stdout=PIPE, stderr=PIPE) 
Popen(["./foo", ], stdin=p0.stdout, stdout=PIPE, stderr=PIPE) 

難道我做錯了什麼? 爲什麼我不能使用gzip.open('bar')作爲stdin參數給Popen?

回答

4

由於子進程的「標準輸入」和「標準輸出」採用文件描述符(這是一個數字),它是操作系統資源。這被掩蓋的事實是,如果你傳遞一個對象,子進程模塊檢查該對象是否有'fileno'屬性,如果它有,它將使用它。

'gzip'對象不是操作系統提供的。一個打開的文件是一個套接字,一個管道。 Gzip對象是一個提供read()和write()方法但沒有fileno屬性的對象。

雖然您可以查看子進程的communications()方法,但可能需要使用它。

+0

是的,我實際上使用p = Popen([...]),然後閱讀p.communicate()[0]。 另外,我的程序不叫做foo,我的輸入文件也不叫吧;-) 所以你說這不是一個簡單的修復? 我發現它很奇怪,Popen([「./ foo」,],stdin = gzip.open('bar'),stdout = PIPE,stderr = PIPE) 工作(雖然返回錯誤的輸出)並且不會引發例外。儘管它可能沒有fileno屬性,但它仍然在使用它。 – 2010-04-28 20:35:43

+0

來自子流程模塊的'PIPE'和'STDOUT'屬性是'特殊常量';在stderr = STDOUT的情況下,常量表示應該傳遞給客戶端進程的fileno應該是相同的,並將其作爲stdout傳遞。在PIPE的情況下,使用操作系統的'pipe()'命令創建一個新的fileno,將一半的管道(實際上是2個數字)傳遞給客戶端進程,並向您發送一個。無論寫入哪一部分,都可以從其他部分讀取。你不能簡單地修復它,需要更多的編程。 – ondra 2010-04-29 07:09:10

相關問題