Domanda

Come puoi creare un FIFO temporaneo (chiamato pipe) in Python? Questo dovrebbe funzionare:

import tempfile

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

Tuttavia, sono titubante a causa del grande avvertimento in Python Docs 11.6 e potenziale rimozione perché obsoleta.

MODIFICA : è interessante notare che ho provato tempfile.NamedTemporaryFile (e per estensione tempfile.mkstemp ), ma os .mkfifo genera:

  

OSError -17: il file esiste già

quando lo esegui sui file creati da mkstemp / NamedTemporaryFile.

È stato utile?

Soluzione

os.mkfifo () fallirà con l'eccezione OSError: [Errno 17] Il file esiste se il file esiste già, quindi non c'è nessun problema di sicurezza qui. Il problema di sicurezza con l'utilizzo di tempfile.mktemp () è la condizione della competizione in cui è possibile per un utente malintenzionato creare un file con lo stesso nome prima di aprirlo da soli, ma poiché os.mkfifo () ha esito negativo se il file esiste già non è un problema.

Tuttavia, poiché mktemp () è deprecato, non dovresti usarlo. Puoi usare tempfile.mkdtemp () invece:

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)

EDIT: dovrei chiarire che, solo perché la vulnerabilità mktemp () è evitata da questo, ci sono ancora gli altri soliti problemi di sicurezza che devono essere considerati; per esempio. un utente malintenzionato potrebbe creare il quindicesimo (se avessero le autorizzazioni adeguate) prima che il programma lo facesse, il che potrebbe causare l'arresto anomalo del programma se errori / eccezioni non vengono gestiti correttamente.

Altri suggerimenti

Che ne dici di usare

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

Se è destinato all'uso nel tuo programma e non con qualsiasi esterno, dai un'occhiata a Modulo di coda . Come ulteriore vantaggio, le code di Python sono thread-safe.

Potresti trovare utile usare il seguente gestore di contesto, che crea e rimuove il file temporaneo per te:

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

Puoi usarlo, ad esempio, in questo modo:

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")

In effetti, tutto ciò che fa mkstemp è eseguire mktemp in un ciclo e continua a tentare di creare esclusivamente fino a quando non riesce (vedi codice sorgente stdlib qui ). Puoi fare lo stesso con 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")

Perché non usare mkstemp () ?

Ad esempio:

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)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top