Создать временный FIFO (именованный канал) в Python? - PullRequest
25 голосов
/ 16 сентября 2009

Как вы можете создать временный FIFO (именованный канал) в Python? Это должно работать:

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 Docs 11.6 и потенциального удаления, потому что оно устарело.

РЕДАКТИРОВАТЬ : Примечательно, что я пробовал tempfile.NamedTemporaryFile (и с расширением tempfile.mkstemp), но os.mkfifo бросает:

OSError -17: файл уже существует

при запуске файлов, созданных mkstemp / NamedTevenFile.

Ответы [ 6 ]

25 голосов
/ 16 сентября 2009

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 (если у него есть подходящие разрешения) до того, как это сделает ваша программа, что может привести к ее аварийному завершению, если ошибки / исключения не обрабатываются должным образом.

3 голосов
/ 27 февраля 2019

Вам может пригодиться следующий контекстный менеджер, который создает и удаляет временный файл для вас:

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")
3 голосов
/ 16 сентября 2009

Если это для использования в вашей программе, а не с внешними, взгляните на Модуль очереди . В качестве дополнительного преимущества очереди Python являются потокобезопасными.

3 голосов
/ 16 сентября 2009

Как насчет использования

d = mkdtemp()
t = os.path.join(d, 'fifo')
1 голос
/ 16 сентября 2015

По сути, все, что делает 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")
0 голосов
/ 16 сентября 2009

Почему бы просто не использовать 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...