Python でテンポラリファイル/ディレクトリを作成する (tempfile)

テンポラリディレクトリを作成する

自動削除されるテンポラリディレクトリ (TemporaryDirectory)

Python の tempfile モジュールが提供する TemporaryDirectory クラスを使用して、テンポラリディレクトリを作成することができます。 TemporaryDirectory オブジェクトを with 文に渡すと、as 節の変数として、作成されたテンポラリディレクトリのパスを取得できます。

テンポラリディレクトリの作成
import os
import tempfile

with tempfile.TemporaryDirectory() as dirname:
    print(dirname)  # => /tmp/tmp98olubfz
    print(os.path.isdir(dirname))  # => True

# with を抜けるとテンポラリディレクトリは既に削除されている
print(os.path.isdir(dirname))  # => False

テンポラリディレクトリは、with ブロックの実行コンテキストを抜けるときに自動的に削除されることに注意してください(__exit__ メソッドの実装で cleanup メソッドが呼ばれており、自動的にディレクトリが削除される仕組みになっています)。 よって、Python プログラムの中で、明示的にテンポラリディレクトリを削除する必要はありません。

自動削除されないテンポラリディレクトリ (mkdtemp)

実行コンテキストを抜けても自動削除されないテンポラリディレクトリを作成したい場合は、tempfile.TemporaryDirectory クラスの代わりに、tempfile.mkdtemp 関数を使用します。 作成されたテンポラリディレクトリは、プログラムを終了してからユーザーが手動で削除しなければいけないので、分かりやすいディレクトリに作成しておいた方がよいでしょう。 次の例では、カレントディレクトリ (.) に、.tmp サフィックスの付いたテンポラリディレクトリを作成しています。

(自動削除されない)テンポラリディレクトリの作成
import tempfile

dirname = tempfile.mkdtemp(dir=".", suffix=".tmp")
print(dirname)  # => ./tmpu57g67kg.tmp

この Python プログラムを実行終了した後にも、テンポラリディレクトリが残っていることを確認してください。 ちなみに、dirprefix, suffix といったパラメーターは、tempfile.TemporaryDirectory クラスのコンストラクタにも指定できますが、あまり使用することはないでしょう(自動削除されるのでパスを知る必要がない)。

テンポラリファイルを作成する

自動削除されるテンポラリファイル (TemporaryFile)

テンポラリファイルを作成するには、tempfile.TemporaryFile 関数を使用します。 この関数は、open 関数と同様にファイルオブジェクトを返します。 パラメーターにも open 関数と同様のものを指定できます。 次の例では、テキスト形式で読み書き可能なテンポラリファイルを作成しています。 同じファイルオブジェクトで書き込みと読み取りを行うため、mode パラメーターには "w+" を指定しています。

テンポラリファイルの作成
import tempfile

with tempfile.TemporaryFile(mode="w+", encoding="utf-8", newline="\n") as fp:
    # テンポラリファイルへ書き込む
    fp.write("Hello\n")
    fp.write("World\n")

    # テンポラリファイルの内容を読み込む
    fp.seek(0)
    lines = fp.readlines()
    print(lines)  # => ['Hello\n', 'World\n']

TemporaryDirectory と同様に、TemporaryFile で作成したテンポラリファイルは、with 文の実行コンテキストを抜けるときに自動的に削除されることに注意してください。

パスを取得可能なテンポラリファイル (NamedTemporaryFile)

テンポラリファイルの名前が必要な場合は、TemporaryFile の代わりに、NamedTemporaryFile を使用する必要があります。 こちらを使わないと、ファイルオブジェクトの name プロパティでファイル名を参照できません。

import tempfile

def cat(filename: str) -> None:
    """指定されたファイル名のファイルの内容を標準出力に出力する"""
    with open(filename, "r", encoding="utf-8") as fp:
        print(fp.read())

with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", newline="\n") as fp:
    # テンポラリファイルへ書き込む
    fp.write("Line 1\n")
    fp.write("Line 2\n")
    fp.write("Line 3")
    fp.flush()

    # テンポラリファイルの名前を使って何らかの処理
    cat(fp.name)

自動削除されないテンポラリファイル (mkstemp)

実行コンテキストを抜けても自動削除されないテンポラリファイルを作るには、tempfile.mkstemp 関数を使用します。 指定できるパラメーターは mkdtemp 関数によるディレクトリ作成とほぼ同様で、出力先のディレクトリ (dir) や、プレフィックス (prefix)、サフィックス (suffix) を指定できます。 mkstemp 関数は、戻り値としてテンポラリファイルのデスクリプター (int) とファイル名 (str) を返します。

(自動削除されない)テンポラリファイルの作成 - 方法 1
import tempfile

# テンポラリファイルの生成
fd, filename = tempfile.mkstemp(dir=".", suffix=".txt")
print(fd)  # => 3
print(filename)  # => /Users/maku/myapp/tmplal4nz7v.txt

# 書き込み
with open(filename, mode="w", encoding="utf-8", newline="\n") as f:
    f.write("Hello\n")
    f.write("World\n")

# 読み込み
with open(filename, mode="r", encoding="utf-8") as f:
    print(f.readlines())  # => ['Hello\n', 'World\n']

# 明示的に削除するなら
# os.remove(filename)

NamedTemporaryFile 関数で delete=False プロパティを指定することでも、自動削除されないテンポラリファイルを作成できるようです。

(自動削除されない)テンポラリファイルの作成 - 方法 2
import tempfile

# テンポラリファイルの生成と書き込み
with tempfile.NamedTemporaryFile(
    mode="w", encoding="utf-8", newline="\n", dir=".", suffix=".txt", delete=False
) as fp:
    filename = fp.name
    fp.write("Hello\n")
    fp.write("World\n")

# 自動削除しないように設定 (delete=False) したので、テンポラリファイルは残っている
with open(filename, mode="r", encoding="utf-8") as f:
    print(f.readlines())  # => ['Hello\n', 'World\n']