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 の大きな警告と非推奨であるため削除される可能性があるため、私はためらっています。
[〜#〜] edit [〜#〜]:私が試したのは注目に値しますtempfile.NamedTemporaryFile
(および拡張子tempfile.mkstemp
)、 だが os.mkfifo
スロー:
OSError -17:ファイルはすでに存在します
mkstemp/NamedTemporaryFileが作成したファイルに対してそれを実行すると。
ファイルが既に存在する場合、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を作成し(適切な権限がある場合)、エラー/例外が適切に処理されない場合にプログラムがクラッシュする可能性があります。
一時ファイルを作成して削除する次のコンテキストマネージャーを使用すると便利です。
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")
使ってみて
d = mkdtemp()
t = os.path.join(d, 'fifo')
それがあなたのプログラム内で使用するためのものであり、どの外部機能も使用していない場合は、 Queue module を参照してください。追加の利点として、pythonキューはスレッドセーフです。
事実上、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")