2013-03-14 62 views
1

殼執行這個讓我切實的成果:子處理管道寫入文件故障

wget -O c1 --no-cache "http://some.website" | sed "1,259d" c1 | sed "4,2002d" 

在Python這樣做讓我什麼:

subprocess.call(shlex.split("wget -O c1 --no-cache \"http://some.website/tofile\"")) 
c1 = open("c1",'w') 
first = subprocess.Popen(shlex.split("sed \"1,259d\" c1"), stdout=subprocess.PIPE) 

subprocess.Popen(shlex.split("sed \"4,2002d\""), stdin=first.stdout, stdout=c1) 
c1.close() 

這樣做也讓我沒有結果:

c1.write(subprocess.Popen(shlex.split("sed \"4,2002d\""), stdin=first.stdout, stdout=subprocess.PIPE).communicate()[0]) 

通過'我什麼都沒有'我的意思是文件中的空白輸出。有人在這裏看到任何不尋常的東西嗎?

+0

你在Python命令行解釋器中試過這個嗎?在這個過程的每一步中,各種變量顯示的是什麼? – 2013-03-14 05:32:44

+0

它們是subprocess.Popen對象。 'c1'當然只是一個文件對象。 – eazar001 2013-03-14 05:38:18

回答

2

c1 = open("c1",'w')打開文件c1寫入並截斷任何現有數據的聲明,所以一切wget的寫入到文件的調用SED之前被擦除。

無論如何,我認爲shlex.split是一般的尷尬。我更喜歡手工打造的args列表:

from subprocess import Popen, PIPE 

p0 = Popen(['wget', '-O', '-', 'http://www.google.com'], stdout=PIPE) 
p1 = Popen(['sed', '2,8d'], stdin=p0.stdout, stdout=PIPE) 
with open('c1', 'w') as c1: 
    p2 = Popen(['sed', '2,7d'], stdin=p1.stdout, stdout=c1) 
    p2.wait() 

然而,沒有明顯的原因Python程序員應該要叫出來的sed。 Python有字符串方法和正則表達式。此外,而不是wget,你可以使用urllib2.urlopen

+0

稍作修改,將p0放在'with'之外並放入p0。在它之後等待(),運行p1而不用管道連接到p0,並且一切都很好。是的,我意識到urllib可以完成工作,我只是想知道爲什麼這不起作用。感謝您的建議,但。 – eazar001 2013-03-14 09:13:06

+0

@ eazar001:p1從p0獲取其數據。我測試過了,它在我的最後工作。不過,我確實忘了「等待」。 – eryksun 2013-03-14 09:30:06

+0

我的解決方法是打開一個'cc1'並輸出。然後運行一個過程來簡單地'mv cc1 c1'。有點骯髒,但它的工作。呃,關於等待。發生這種事情,我想wget需要一段時間才能完成工作。 – eazar001 2013-03-14 09:35:37

1

爲什麼不只是在管道中做所有事情並將輸出發送到文件?

wget -O - "http://www.google.com" | sed "1,259d" | sed "4,2002d" > c1 

或者,如果你不想把它發送到一個文件,並希望它在標準輸出上,而不是:

wget -O - "http://www.google.com" | sed "1,259d" | sed "4,2002d" 

如果你想這樣做在Python:

pipe = subprocess.Popen(shlex.split("wget -O - \"http://www.google.com\" | sed \"1,259d\" | sed \"4,2002d\""), stdout=subprocess.PIPE) 
result = pipe.communicate()[0] 
+1

能夠使用您的建議的變體,它的工作。謝謝你的幫助。 – eazar001 2013-03-14 06:51:01

3

我總是使用plumbum來運行外部命令。它提供了一個非常直觀的界面,當然,照顧我逃跑。

看起來是這樣的:

from plumbum.cmd import wget, sed 
cmd1 = wget['-O', 'c1']['--no-cache']["http://some.website"] 
cmd2 = sed["1,259d"]['c1'] | sed["4,2002d"] 
print cmd1 
cmd1() # run it 
print cmd2 
cmd2() # run it 
+0

這絕對是一個有用的工具,我不得不嘗試一下。 – eazar001 2013-03-14 06:52:43

0

爲了讓那些或多或少都會遇到相同類型問題的人們更容易生活,我決定發佈最終修訂後的代碼,這個代碼在有關c1的評論中進行了考慮,並覆蓋了數據。特別感興趣的是使用communicate(),這有助於完全消除殭屍進程的任何表現,這是令人非常惱火的。另外,我發現在不需要管道的部分使用subprocess.call是有用的。沒有wait()最後是必要的。最終,遠離sedwget是個不錯的主意,尤其是使用Python的內置工具和urllib2

p0 = subprocess.call(shlex.split("wget -Oc1 --no-cache \"http://Some.website/tofile\"")) 
p1 = subprocess.Popen(shlex.split("sed \"1,261d\" c1"), stdout=subprocess.PIPE) 

with open("cc1", 'w') as cc1: 
    p2 = subprocess.Popen(shlex.split("sed \"3,2002d\""), stdin=p1.stdout, stdout=cc1) 
    p2.communicate() 
    p1.communicate() 
    p3 = subprocess.call(shlex.split("mv cc1 c1"))