Q1次のうち、フォルダごと再帰的に削除したいときに使うのはどれですか?
shutil と tempfile — ファイル一括操作と一時ファイル
shutil.copy/move/rmtreeでファイルとフォルダを一括操作し、tempfile.NamedTemporaryFileのdelete切り替えと一時ファイル経由のアトミック書き込みを、実行しながら学びます。
ファイルとフォルダを丸ごと操作する shutilと、使い捨ての一時ファイルを扱うtempfileの 2 つを整理します。shutil.copy / move / rmtreeによるファイル一括操作、NamedTemporaryFileの安全な使い方、両者を組み合わせたアトミック書き込みパターンまで扱います。
shutil — ファイルとフォルダの操作を 1 行で書く
shutilはshell utilitiesの略で、シェル(コマンドライン)でcp / mv / rm -rのように使う操作をPython のコードから 1 行で呼び出せる標準ライブラリです。osモジュールにもos.renameなどはありますが、shutilは再帰的なフォルダコピーやツリー削除といった、よりまとまった単位の操作を提供します。
| 関数 | 動作 | 備考 |
|---|---|---|
| shutil.copy(src, dst) | ファイルを複製する | dst がフォルダなら同名でその中に作る |
| shutil.copy2(src, dst) | copy + 更新日時などのメタ情報も保持 | バックアップ用途に向く |
| shutil.copytree(src, dst) | フォルダごと再帰的に複製する | dst は存在してはいけない |
| shutil.move(src, dst) | ファイルやフォルダを移動・名前変更する | 同じパス上なら rename と等価 |
| shutil.rmtree(path) | フォルダと配下を再帰的に削除する | 戻せない。実行前に対象パスをよく確認する |
import shutil
import os
# 1) ファイルを別の場所にコピー (バックアップを作る典型例)
os.makedirs("backups", exist_ok=True) # コピー先のフォルダを用意
shutil.copy("data/sales.csv", "backups/sales_2024.csv")
shutil.move("logs/temp.log", "logs/archive_2024.log")
shutil.rmtree("old_data")
rmtree は取り消せない
shutil.rmtree(path)はpath配下を物理削除します。Python では「ゴミ箱」を経由せず、即座に消えます。実プロジェクトで使うときは消す対象を print で確認する、if path.startswith("/tmp") のようなガードを入れるなど、人間と機械の両方で守る慣習を付けましょう。
tempfile — 安全に使い捨てファイルを作る
tempfileは使い終わったら自動で消える一時ファイルを作るための標準ライブラリです。中間結果の保存・大量データの一時バッファ・テストの作業フォルダなど、「処理中だけ存在すれば良いファイル」のために使います。
手でtmp_xxx.txtのようなファイル名を考えると他のプロセスとぶつかったり消し忘れたりしがちですが、tempfileはOS の一時フォルダに重複しないファイル名で作り、処理が終わったら自動で消してくれます。
withブロックに入った瞬間にファイルが作られ、ブロックを抜けるときに自動で削除される。ファイル名はその場で衝突しない名前が割り当てられるので、自分で命名する必要がない。| 関数・属性 | 意味 | 備考 |
|---|---|---|
| tempfile.NamedTemporaryFile | with で開閉する一時ファイル | delete=False で抜けても残す |
| tempfile.mkdtemp() | 一時フォルダのパスを返す | 削除は自分で shutil.rmtree |
| tempfile.gettempdir() | OS の一時フォルダのパスを返す | Linux なら /tmp、macOS は別パス |
| tf.name | 実ファイルパス(ランダム名) | with の中で参照できる |
| tf.write / tf.read | ファイルオブジェクトと同じ API | mode 引数で 'w' / 'r' / 'w+' を選ぶ |
import tempfile
import os
# with で安全に作って自動削除
with tempfile.NamedTemporaryFile(mode="w+", suffix=".txt", delete=True) as tf:
tf.write("集計結果の中間データ\n")
tf.seek(0)
print("中身:", tf.read())
print("パス:", tf.name)
# ← ここでブロックを抜けて自動削除される
delete=False と with を組み合わせる場面
書いてから別の場所で読み戻したいときはdelete=Falseを指定して、withを抜けてもファイルが残るようにします。残したファイルは使い終わったら自分で os.remove(path) するか、後述のアトミック書き込みのようにshutil.moveで本来の保存先に置き換えます。
`delete=True`で自動削除される一時ファイル
重要な設定ファイルや状態ファイルを直接open("settings.json", "w")で書き換えると、書き込み途中でプロセスが落ちたときにファイルが半分書かれた状態で残ってしまい、次回読み込み時にパースエラーになります。これを避ける定石が「一時ファイルに書ききってから、本来の場所に rename / move する」というアトミック書き込み(atomic、途中で中断されても「完了したか / していないか」しか観測できない更新方式)パターンです。
import tempfile
import shutil
import json
final_path = "settings.json"
new_settings = {"theme": "dark", "lang": "ja", "fontSize": 14}
# 1) 一時ファイルに書き切る
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".json") as tf:
json.dump(new_settings, tf)
temp_path = tf.name
# 2) 完了したら本物のパスに移動 (この瞬間だけが「切り替わり」のタイミング)
shutil.move(temp_path, final_path)
# 3) 確認
with open(final_path) as f:
print(json.load(f))
# → {'theme': 'dark', 'lang': 'ja', 'fontSize': 14}
ファイルオブジェクトには「現在の読み書き位置(カーソル)」があり、tf.write(...)を呼ぶとカーソルは書いた直後の位置(= 末尾)に移動します。そのままtf.read()を呼ぶとカーソルから後ろに何も無いため空文字が返るので、tf.seek(0)でカーソルを先頭に戻してから読み直す、というのが定石です。
mode="w+" は読み書き両用のモード
mode="w+"は書き込みと読み込みを同じファイルハンドルで両方できるモードです。"w"だけだと書き込み専用でread()が使えず、"r"だけだと読み込み専用でwrite()が使えません。書いてすぐ読み戻す演習では"w+"が必須になります。
理解度チェック
まずは1問ずつ答えてみましょう。
Q2tempfile.NamedTemporaryFileをdelete=False 付きで使う典型的な理由として正しいのはどれですか?
Q3アトミック書き込みの本質は次のうちどれですか?