如何在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 Docs 11.6中的重大警告和潜在的删除,因为它已被弃用。
编辑:值得注意的是,我已尝试tempfile.NamedTemporaryFile
(并且通过扩展程序tempfile.mkstemp
),但os.mkfifo
会抛出:
OSError -17:文件已存在
在mkstemp / NamedTemporaryFile创建的文件上运行它时。
答案 0 :(得分:25)
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(如果他们有合适的权限),如果没有正确处理错误/异常,可能会导致程序崩溃。
答案 1 :(得分:3)
如何使用
d = mkdtemp()
t = os.path.join(d, 'fifo')
答案 2 :(得分:3)
如果要在您的程序中使用,而不是在任何外部使用,请查看Queue module。另外一个好处是,python队列是线程安全的。
答案 3 :(得分:2)
使用以下上下文管理器可能会很方便,它会为您创建和删除临时文件:
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")
答案 4 :(得分:1)
实际上,mkstemp
执行的所有操作都在循环中运行mktemp
并继续尝试专门创建,直到成功为止(请参阅stdlib源代码here)。您可以使用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")
答案 5 :(得分:-1)
为什么不使用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)