python - 关闭前冲洗管道 (os.pipe)

标签 python pipe ipc buffering

我需要启动一个子进程并启用两个线程来读取其 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()上.

我可以看出这是一个缓冲问题,因为如果我输入一个非常糟糕的time.sleep(0.1)就在subprocess.check_call(...)之后一切都神奇地起作用。

最好的方法是刷新而不是等待,但是任何对 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,那么您将更容易将它们视为文件对象。 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)

关于python - 关闭前冲洗管道 (os.pipe),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25866092/

相关文章:

python - 使用 pymongo 插入嵌套字段时清理用户输入

python - fusion_matrix - 太多值无法解压

python - Keras 的 CategoricalCrossEntropy 到底在做什么?

Bash 管道 : split input after 1st line, 在第 1 行和其余行上运行不同的命令

c++ - 如何将函数传输到匿名管道 WinAPI?

python - 如何在 QComboBox 中居中文本?

filter - 管道和过滤器

c++ - Linux 共享库中的单例无法按预期工作

c - IPC FIFO 生产者-消费者死锁

c# - 为什么 Process.Start 在 asp.net web 服务中不起作用?