web-dev-qa-db-ja.com

Pythonで一時的なFIFO(名前付きパイプ)を作成しますか?

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が作成したファイルに対してそれを実行すると。

26
Brian M. Hunt

ファイルが既に存在する場合、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を作成し(適切な権限がある場合)、エラー/例外が適切に処理されない場合にプログラムがクラッシュする可能性があります。

25
mhawke

一時ファイルを作成して削除する次のコンテキストマネージャーを使用すると便利です。

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")
5
nirvana-msu

使ってみて

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

それがあなたのプログラム内で使用するためのものであり、どの外部機能も使用していない場合は、 Queue module を参照してください。追加の利点として、pythonキューはスレッドセーフです。

3
nilamo

事実上、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")
1
eestrada