Pythonのtempfile
モジュールを使用して、一時ファイル名を付けることができます。time.time()
複数のスレッドで同時に使用された場合に同じ名前を返す可能性のある一時ファイルを使用して作成するのではなく、スレッドセーフな方法で一時ファイルを作成できます。
あなたの質問へのコメントで示唆されているように、これはコンテキストマネージャーの使用と組み合わせることができます。Pythonのソースを見ると、やりたいことを実装する方法についていくつかのアイデアを得ることができtempfile.py
ます。
次のコードスニペットは、あなたが望むことをするかもしれません。から返されたオブジェクトの内部の一部を使用しますtempfile
。
- 一時ファイルの作成はスレッドセーフです。
- 正常に完了したときのファイルの名前変更は、少なくともLinuxではアトミックです。
os.path.exists()
との間にはos.rename()
、競合状態を引き起こす可能性のある個別のチェックはありません。Linuxでのアトミックな名前変更の場合、ソースと宛先は同じファイルシステム上にある必要があります。そのため、このコードは一時ファイルを宛先ファイルと同じディレクトリに配置します。
RenamedTemporaryFile
クラスはNamedTemporaryFile
、コンテキストマネージャーを使用して閉じられた場合を除いて、ほとんどの目的でのように動作する必要があり、ファイルの名前が変更されます。
サンプル:
import tempfile
import os
class RenamedTemporaryFile(object):
"""
A temporary file object which will be renamed to the specified
path on exit.
"""
def __init__(self, final_path, **kwargs):
tmpfile_dir = kwargs.pop('dir', None)
# Put temporary file in the same directory as the location for the
# final file so that an atomic move into place can occur.
if tmpfile_dir is None:
tmpfile_dir = os.path.dirname(final_path)
self.tmpfile = tempfile.NamedTemporaryFile(dir=tmpfile_dir, **kwargs)
self.final_path = final_path
def __getattr__(self, attr):
"""
Delegate attribute access to the underlying temporary file object.
"""
return getattr(self.tmpfile, attr)
def __enter__(self):
self.tmpfile.__enter__()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is None:
self.tmpfile.delete = False
result = self.tmpfile.__exit__(exc_type, exc_val, exc_tb)
os.rename(self.tmpfile.name, self.final_path)
else:
result = self.tmpfile.__exit__(exc_type, exc_val, exc_tb)
return result
その後、次のように使用できます。
with RenamedTemporaryFile('whatever') as f:
f.write('stuff')
書き込み中、内容は一時ファイルに移動し、終了時にファイルの名前が変更されます。このコードはおそらくいくつかの調整が必要ですが、一般的な考え方はあなたが始めるのに役立つはずです。