Создать временный FIFO (именованный канал) в Python?

как вы можете создать временный 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.NamedTemporaryFiletempfile.mkstemp), но os.mkfifo броски:

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

когда вы запускаете его в файлах что mkstemp / NamedTemporaryFile создали.

5 ответов


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)

ИЗМЕНИТЬ: I должно быть ясно, что, просто потому, что mktemp() уязвимость предотвращается этим, есть еще другие обычные проблемы безопасности, которые необходимо учитывать; например, злоумышленник может создать fifo (если у них есть подходящие разрешения) до вашей программы, что может привести к сбою вашей программы, если ошибки/исключения не обрабатываются должным образом.


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

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

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


эффективно, все это mkstemp does is run 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")

почему бы просто не использовать 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)