簡體   English   中英

python子進程:從管道讀取而不關閉它

[英]python subprocess: read from pipe without closing it

我有一個將連續字節流寫入stdout的進程。 我有另一個過程,它從第一個過程的標准輸出中讀取,然后完成。 但是我發現第二個進程完成時,它關閉了管道(我認為),因此進程1停止運行。

我嘗試了兩種不同的方式:

在外殼1中:

# make fifo
mkfifo /tmp/camera
# stream video from my webcam to the pipe
ffmpeg -y -f v4l2 -r 10 -i /dev/video0 -f avi /tmp/camera

在外殼2中:

# attach to pipe and take a snapshot
rrmpeg -y -r 1 -f avi -i /tmp/camera -vframes 1 -s 160x120 -f image2 image1.jpg

我也在shell 2中嘗試過,結果相同:

tail -f /tmp/camera

當外殼2中的進程停止時,它將終止進程1。為什么?

我嘗試的第二件事是使用python子進程:

from subprocess import Popen, PIPE
import shlex, time

stream = Popen(shlex.split("ffmpeg -y -f v4l2 -r 10 -i /dev/video0 -f avi -"), stdout=PIPE)
while True:
    time.sleep(3)
    snap = Popen(shlex.split("rrmpeg -y -r 1 -f avi -i - -vframes 1 -s 160x120 -f image2 image1.jpg"), stdin=stream.stdout)

它在循環中第一次起作用,但是當snap進程超出范圍時, stream進程終止。

有什么方法可以在不關閉進程1的情況下讀取其中的某些流?

是的,有一種方法可以永遠繼續管道編寫器。 為此,您必須確保

  1. 至少有一個閱讀器保持管道暢通 (沒有讀數是可以的)-或-
  2. 作者忽略SIGPIPE並很好地處理write()錯誤(即重試)

第二個選項不是那么簡單(無需更改/檢查編寫器的源代碼),因為沒有讀取器的管道上的write()不會阻塞(一旦讀取器在那里)。

對於第一個選項,請確保您的第一個閱讀器打開了fifo / pipe,不從中讀取任何內容,然后永遠阻止/休眠某些東西而不會死。

讓任何連續的讀者來做這項工作。 他們可以打開fifo(命名管道),也可以從讀取端打開的過程中分叉(它們繼承了filedescriptor)。

這樣,就不會生成SIGPIPE,並且一旦管道緩沖區已滿,write()將阻止編寫器。

man 7 pipe告訴你更多。

(注意:如果write()阻止意外的長時,某些程序可能會感到困惑。例如,一些經常掛在牆上的應用程序。)

關於“當shell 2中的進程停止時,它殺死進程1。為什么?”

進程1可能被SIGPIPE殺死了(我沒有檢查源代碼),當它在沒有讀取器的管道上嘗試write()時,它將獲得該信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM