58

一部のデータを一時ファイルに書き込む必要がある Python スクリプトを作成してから、一時ファイルを読み取る C++ プログラムを実行するサブプロセスを作成しています。私はNamedTemporaryFileこれに使用しようとしていますが、ドキュメントによると、

名前付きの一時ファイルがまだ開いている間に、その名前を使用してファイルを 2 度目に開くことができるかどうかは、プラットフォームによって異なります (Unix では使用できますが、Windows NT 以降では使用できません)。

実際、Windows では、書き込み後に一時ファイルをフラッシュしても、一時ファイルが消えるまで閉じないと、サブプロセスは読み取り用に開くことができません。

delete=Falseでファイルを作成し、サブプロセスを生成する前にファイルを閉じ、完了したら手動で削除することで、これを回避しています。

fileTemp = tempfile.NamedTemporaryFile(delete = False)
try:
    fileTemp.write(someStuff)
    fileTemp.close()
    # ...run the subprocess and wait for it to complete...
finally:
    os.remove(fileTemp.name)

これはエレガントではないようです。これを行うより良い方法はありますか?おそらく、サブプロセスがアクセスできるように、一時ファイルのアクセス許可を開く方法はありますか?

4

5 に答える 5

26

他の誰もこの情報を公開することに興味を持っていないように見えるので...

tempfilemkdtemp()は、この問題を矮小化できる関数 を公開します。

try:
    temp_dir = mkdtemp()
    temp_file = make_a_file_in_a_dir(temp_dir)
    do_your_subprocess_stuff(temp_file)
    remove_your_temp_file(temp_file)
finally:
    os.rmdir(temp_dir)

mkstemp()一時ファイル自体のセキュリティを強化するために使用したり、ファイルを削除する前にその場で上書きしたりしたい場合があるため、中間関数の実装は読者に任せます。のソースを熟読しても簡単に計画できないセキュリティ制限が何であるかは特にわかりませんtempfile

とにかく、はい、NamedTemporaryFileWindows での使用は洗練されていない可能性があり、ここでの私のソリューションも洗練されていない可能性がありますが、Windows のサポートは洗練されたコードよりも重要であると既に判断しているため、先に進んで読みやすいものを実行することもできます。

于 2013-03-06T22:27:25.497 に答える
24

リチャード・オウドケルクによると

(...) NamedTemporaryFileWindows で a を再オープンしようとして失敗する唯一の理由は、再オープンするときに を使用する必要があるためO_TEMPORARYです。

そして彼はPython 3.3+でこれを行う方法の例を挙げています

import os, tempfile

DATA = b"hello bob"

def temp_opener(name, flag, mode=0o777):
    return os.open(name, flag | os.O_TEMPORARY, mode)

with tempfile.NamedTemporaryFile() as f:
    f.write(DATA)
    f.flush()
    with open(f.name, "rb", opener=temp_opener) as f:
        assert f.read() == DATA

assert not os.path.exists(f.name)

openerPython 2.xのビルトインにはパラメーターがないため、同じ効果を得るには、open()下位レベルos.open()と関数を組み合わせる必要があります。os.fdopen()

import subprocess
import tempfile

DATA = b"hello bob"

with tempfile.NamedTemporaryFile() as f:
    f.write(DATA)
    f.flush()

    subprocess_code = \
    """import os
       f = os.fdopen(os.open(r'{FILENAME}', os.O_RDWR | os.O_BINARY | os.O_TEMPORARY), 'rb')
       assert f.read() == b'{DATA}'
    """.replace('\n', ';').format(FILENAME=f.name, DATA=DATA)

    subprocess.check_output(['python', '-c', subprocess_code]) == DATA
于 2013-03-05T22:40:56.207 に答える
13

いつでも低レベルに進むことができますが、それが十分にクリーンであるかどうかはわかりません:

fd, filename = tempfile.mkstemp()
try:
    os.write(fd, someStuff)
    os.close(fd)
    # ...run the subprocess and wait for it to complete...
finally:
    os.remove(filename)
于 2013-03-02T01:04:53.747 に答える