Comment pouvez-vous créer un FIFO (canal nommé) temporaire en Python? Cela devrait fonctionner:
import tempfile
temp_file_name = mktemp()
os.mkfifo(temp_file_name)
open(temp_file_name, os.O_WRONLY)
# ... some process, somewhere, will read it ...
Cependant, j'hésite à cause du gros avertissement dans Python Docs 11.6 et de la suppression potentielle car elle est obsolète.
[~ # ~] modifier [~ # ~] : il est à noter que j'ai essayé tempfile.NamedTemporaryFile
(et par extension tempfile.mkstemp
), mais os.mkfifo
jette:
OSError -17: le fichier existe déjà
lorsque vous l'exécutez sur les fichiers créés par mkstemp/NamedTemporaryFile.
os.mkfifo()
échouera à l'exception OSError: [Errno 17] File exists
si le fichier existe déjà, il n'y a donc pas de problème de sécurité ici. Le problème de sécurité avec l'utilisation de tempfile.mktemp()
est la condition de concurrence où il est possible pour un attaquant de créer un fichier avec le même nom avant de l'ouvrir vous-même, mais puisque os.mkfifo()
échoue si le fichier existe déjà ce n'est pas un problème.
Cependant, comme mktemp()
est obsolète, vous ne devez pas l'utiliser. Vous pouvez utiliser tempfile.mkdtemp()
à la place:
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: Je dois préciser que, simplement parce que la vulnérabilité mktemp()
est évitée par cela, il y a encore les autres problèmes de sécurité habituels qui doivent être pris en compte; par exemple. un attaquant pourrait créer le fifo (s'il avait les autorisations adéquates) avant que votre programme ne le fasse, ce qui pourrait provoquer le plantage de votre programme si les erreurs/exceptions ne sont pas correctement gérées.
Vous pouvez trouver pratique d'utiliser le gestionnaire de contexte suivant, qui crée et supprime le fichier temporaire pour vous:
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
Vous pouvez l'utiliser, par exemple, comme ceci:
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")
Que diriez-vous d'utiliser
d = mkdtemp()
t = os.path.join(d, 'fifo')
Si c'est pour une utilisation dans votre programme, et non avec des externes, jetez un œil au module Queue . Comme avantage supplémentaire, les files d'attente python sont thread-safe.
En effet, tout ce que mkstemp
fait est exécuté mktemp
dans une boucle et continue de tenter de créer exclusivement jusqu'à ce qu'il réussisse (voir le code source stdlib ici ). Vous pouvez faire de même avec 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")