簡體   English   中英

關閉前沖洗管道(os.pipe)

[英]Flushing a pipe (os.pipe) before closing

我需要啟動一個子進程並啟用兩個線程來分別讀取它的stdoutstderr

以下代碼只是考慮stdout

def reader(rfd):
    while True:
        try:
            data = os.read(rfd, bufsize)
        except OSError:
            break
        else:
            chomp(data)

rout, wout = os.pipe()
tout = threading.Thread(target=reader, args=(rout,))
tout.start()

subprocess.check_call(command, bufsize=bufsize, stdout=wout, stderr=werr)

os.close(wout)
os.close(rout)
tout.join()

代碼工作,除了我注意到並非所有數據都被處理,就好像os.close(wout)函數在讀取所有數據之前殺死了讀者。 另一方面,如果我不關閉wout我的進程將永遠掛在tout.join()

我可以說這是一個緩沖問題,因為如果我在subprocess.check_call(...)之后放一個非常糟糕的time.sleep(0.1) ,一切都神奇地起作用。

好的方法是刷新而不是等待,但是通過管道調用os.fsync()會給出OSError: [Errno 22] Invalid argument

有關如何刷新使用os.pipe創建的管道的任何提示?

我會建議使用Popen而不是os.pipe進程間通信。

例如。

writer_process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
reader_thread = threading.Thread(target=reader, args=(writer_process.stdout,))
reader_thread.start()
reader_thread.join()

但是,如果您真的想使用os.pipe那么您將更容易將它們os.pipe文件對象。 Python的內置文件上下文管理器將確保文件的正確刷新和關閉。

例如。

def reader(fd):
    with os.fdopen(fd, bufsize=bufsize) as f:
        while True:
            data = f.read(bufsize)
            if not data:
                break
            chomp(data)

with os.fdopen(wout, "w", bufsize=bufsize) as f:
    subprocess.check_call(cmd, stdout=f)

在確定進程寫完之前(因為你將丟失數據),你不能關閉管道,並且你不能等待線程完成而不關閉管道(因為os.read將永遠阻塞) 。

您需要等待進程完成,並手動關閉管道的寫入端(因為您創建了它)。

這是一個自包含的例子:

import os
import threading
import subprocess

def reader(rfd):
    while True:
        try:
            data = os.read(rfd, bufsize)
            if not data:
                break #reached EOF
        except OSError:
            break

bufsize=100

rout, wout = os.pipe()
rerr, werr = os.pipe()

tout = threading.Thread(target=reader, args=(rout,))
tout.start()

p= subprocess.Popen("ls", bufsize=bufsize, stdout=wout, stderr=werr)
p.wait() #wait for the proces to end writing
os.close(wout)
os.close(werr)
tout.join()
os.close(rout)
os.close(rerr)

暫無
暫無

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

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