命名管道(缓冲区?)或Python中的共享内存文件

dsekswqp  于 2023-08-08  发布在  Python
关注(0)|答案(1)|浏览(107)

我有一个关于命名管道或Python中类似的东西的问题,以及它们是否可以为我的用例工作。我有类似下面的代码。

fn = path/to/my/file.ext
os.mkfifo(fn)
subprocess.check_output(args=(bar -o fn).split())
foo(fn)

字符串
我的目标是不将子进程条的输出写入光盘,而是直接将其导入foo()函数。遗憾的是,foo()函数只接受文件名,而不接受任何类型的描述符/句柄。因此,我需要定义某种内存文件,它可以被子进程和foo()函数使用。正如我所理解的,命名管道非常接近我想要的,然而它被设计为只在两端连接时工作,而不是作为内存文件/缓冲区中的某种中间体,因此它已经挂起子进程调用(有可能我做错了/理解错了什么)。命名管道是正确的方法还是我应该使用其他方法?
(另外,我也想避免os.O_NONBLOCK这样的东西,因为它们只在Linux上工作)
foo()函数仅从文件中读取。
非常感谢任何帮助!

2uluyalo

2uluyalo1#

命名管道是解决此问题的有效方法。您当前的方法失败,因为subprocess.check_output等待进程终止。在排空管道之前,不会发生这种情况。因此,第一个修复方法是调用subprocess.Popen,并在从管道读取时让进程继续运行。
然而,这又带来了一个新问题:fn如何知道该过程已完成?通常您会读取到文件结尾(EOF)。当写入端关闭时,管道发出EOF信号。对于命名管道,文件系统中的文件条目是一个写入器(打开管道的子进程算作第二个写入器)。因此,fn将无限期地等待EOF。
您需要做的是在该过程完成后删除命名管道。最简单的方法是使用单独的线程。

import os
from os import path
import subprocess
import tempfile
import threading

def call_bar(fifo_name):
    try:
        subprocess.check_output(args=("bar", "-o", fifo_name))
    finally:
        os.remove(fifo_name)

# Python doesn't have a function for safe creation of temporary named
# fifos. So we resort to a temporary directory
with tempfile.TemporaryDirectory() as tmpdir:
    fifo_name = path.join(tmpdir.name, "fifo")
    os.mkfifo(fifo_name)
    with threading.Thread(target=call_bar, args=(fifo_name,)):
        foo(fifo_name)

字符串
这其中有一个问题:如果进程在fn打开管道之前终止,则第二个线程可能会在fn有机会打开管道之前删除管道。我想如果子流程不创建输出,可能会发生这种情况。该异常应该很容易捕获。“

相关问题