在Python中创建一个临时FIFO(命名管道)?(Create a temporary FIFO

2019-07-18 04:00发布

你怎么能在Python中创建一个临时FIFO(命名管道)? 这应该工作:

import tempfile

temp_file_name = mktemp()
os.mkfifo(temp_file_name)
open(temp_file_name, os.O_WRONLY)
# ... some process, somewhere, will read it ...

不过,我因为在大的警告很犹豫Python文档11.6和潜在的去除,因为它的否决。

编辑 :这是值得注意的,我试过tempfile.NamedTemporaryFile (通过扩展tempfile.mkstemp ),但os.mkfifo抛出:

OSERROR -17:文件已存在

当你对mkstemp / NamedTemporaryFile文件运行创造。

Answer 1:

os.mkfifo()将失败,出现异常OSError: [Errno 17] File exists ,如果该文件已经存在,所以在这里不存在安全问题。 使用安全问题tempfile.mktemp()是竞争条件的地方可以让你自己打开之前,攻击者可以创建具有相同名称的文件,但由于os.mkfifo()失败,如果该文件已经存在,这是不是一个问题。

然而,由于mktemp()已经过时,你不应该使用它。 您可以使用tempfile.mkdtemp()代替:

import os, tempfile

tmpdir = tempfile.mkdtemp()
filename = os.path.join(tmpdir, 'myfifo')
print filename
try:
    os.mkfifo(filename)
except OSError, e:
    print "Failed to create FIFO: %s" % e
else:
    fifo = open(filename, 'w')
    # write stuff to fifo
    print >> fifo, "hello"
    fifo.close()
    os.remove(filename)
    os.rmdir(tmpdir)

编辑:我应该说清楚,只是因为mktemp()漏洞是由该避免,仍有需要考虑其他的常规安全问题; 例如,攻击者可以创建的FIFO(如果他们有合适的权限)程序之前做过这可能导致你的程序崩溃,如果错误/异常的处理不当。



Answer 2:

如何使用

d = mkdtemp()
t = os.path.join(d, 'fifo')


Answer 3:

如果这是你的程序中使用,并且不与任何外部组件,看看在队列模块 。 作为一个额外的好处,蟒蛇队列是线程安全的。



Answer 4:

您可能会发现它使用下面的上下文管理,创建和删除临时文件,为您得心应手:

import os
import tempfile
from contextlib import contextmanager


@contextmanager
def temp_fifo():
    """Context Manager for creating named pipes with temporary names."""
    tmpdir = tempfile.mkdtemp()
    filename = os.path.join(tmpdir, 'fifo')  # Temporary filename
    os.mkfifo(filename)  # Create FIFO
    yield filename
    os.unlink(filename)  # Remove file
    os.rmdir(tmpdir)  # Remove directory

您可以使用它,例如,像这样的:

with temp_fifo() as fifo_file:
    # Pass the fifo_file filename e.g. to some other process to read from.
    # Write something to the pipe 
    with open(fifo_file, 'w') as f:
        f.write("Hello\n")


Answer 5:

实际上,所有的mkstemp并运行mktemp一个循环,并不断试图独占创建,直到成功为止(见STDLIB源代码在这里 )。 你可以做同样的os.mkfifo

import os, errno, tempfile

def mkftemp(*args, **kwargs):
    for attempt in xrange(1024):
        tpath = tempfile.mktemp(*args, **kwargs)

        try:
            os.mkfifo(tpath, 0600)
        except OSError as e:
            if e.errno == errno.EEXIST:
                # lets try again
                continue
            else:
                raise
        else:
           # NOTE: we only return the path because opening with
           # os.open here would block indefinitely since there 
           # isn't anyone on the other end of the fifo.
           return tpath
    else:
        raise IOError(errno.EEXIST, "No usable temporary file name found")


Answer 6:

为什么不直接使用mkstemp() ?

例如:

import tempfile
import os

handle, filename = tempfile.mkstemp()
os.mkfifo(filename)
writer = open(filename, os.O_WRONLY)
reader = open(filename, os.O_RDONLY)
os.close(handle)


文章来源: Create a temporary FIFO (named pipe) in Python?