[英]Flushing a pipe (os.pipe) before closing
我需要启动一个子进程并启用两个线程来分别读取它的stdout
和stderr
。
以下代码只是考虑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.