Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案

加入好友
加入社群
Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

為什麼需要 tempfile?
在處理檔案操作時,
我們經常需要建立臨時檔案來儲存中間結果、
處理大型資料,或避免直接修改原始檔案。
手動管理臨時檔案容易遇到以下問題:

⚠️ 常見問題:

檔名衝突(多執行緒/程序同時執行)
權限不足(寫入受保護的目錄)
殘留檔案(程式異常中斷時未清理)
跨平台相容性(Windows/Linux/macOS 臨時目錄不同)
✅ tempfile 的優勢:

自動產生唯一檔名(系統保證不衝突)
使用系統臨時目錄(保證有權限)
支援自動清理(離開作用域後刪除)
跨平台無需修改程式碼
1️⃣ 匯入 tempfile 與系統資訊檢查

import tempfile
import os
import shutil
from pathlib import Path

# 查看系統臨時目錄位置
temp_dir = tempfile.gettempdir()
print(f"系統臨時目錄: {temp_dir}")

# 查看預設前綴
print(f"預設前綴: {tempfile.template}")

# 查看臨時目錄是否可寫
print(f"可寫入: {os.access(temp_dir, os.W_OK)}")

# 不同平台範例
# Windows: C:\Users\XXX\AppData\Local\Temp
# Linux:   /tmp
# macOS:   /var/folders/...

輸出:

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王
  • os.access(path, mode) 的第二個參數叫 mode(常稱「旗標」flags)。
    它是位元旗標的整數,用來指定要檢查哪些存取權限。

可用旗標

  • os.F_OK = 0 ;只檢查路徑是否存在
  • os.R_OK = 4 ;讀取權限
  • os.W_OK = 2 ;寫入權限
  • os.X_OK = 1 ;執行權限

用法要點

  • 多個條件用位元或組合:os.R_OK | os.W_OK 等。
  • os.access(path, os.R_OK | os.W_OK) → 同時要求可讀且可寫。
  • 回傳 True/False,針對目前有效使用者/群組判斷,
    實際開檔仍應處理例外。
Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

2️⃣ NamedTemporaryFile:有檔名的臨時檔案
NamedTemporaryFile 是最常用的臨時檔案類別,
適合需要檔案路徑的場景(例如傳給外部程式或函式庫)。

核心參數

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

範例 2.1:自動刪除的臨時檔案

# 自動刪除的臨時檔案預設行為
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=True) as tmp:
    print(f"✅ 臨時檔案已建立: {tmp.name}")
    
    # 寫入資料
    tmp.write("這是測試資料\n")
    tmp.write("第二行內容\n")
    tmp.flush()  # 強制寫入磁碟重要!)
    
    # 確認檔案存在
    print(f"📂 檔案存在: {os.path.exists(tmp.name)}")

# 離開 with 區塊後自動刪除
print(f"❌ 檔案已被刪除: {not os.path.exists(tmp.name)}")

輸出:

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

範例 2.2:保留臨時檔案

# 保留臨時檔案delete=False
with tempfile.NamedTemporaryFile(mode='w', suffix='.log', delete=False) as tmp:
    tmp_path = tmp.name
    print(f"📝 臨時檔案路徑: {tmp_path}")
    
    tmp.write("日誌記錄 1\n")
    tmp.write("日誌記錄 2\n")

# ✅ 檔案仍存在需手動刪除
print(f"✅ 檔案保留中: {os.path.exists(tmp_path)}")

# 讀取內容
with open(tmp_path, 'r') as f:
    content = f.read()
    print(f"📖 檔案內容:\n{content}")

# 手動清理
os.remove(tmp_path)
print(f"🗑️ 已手動刪除: {not os.path.exists(tmp_path)}")

輸出:

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

3️⃣ TemporaryDirectory:臨時資料夾

適合需要建立多個臨時檔案的場景,
整個資料夾(包含內部所有檔案)會自動清理。

# 臨時資料夾自動清理
with tempfile.TemporaryDirectory(prefix='demo_') as tmpdir:
    print(f"📁 臨時資料夾: {tmpdir}")
    
    # 建立多個檔案
    file1 = Path(tmpdir) / "data.json"
    file2 = Path(tmpdir) / "result.txt"
    
    file1.write_text('{"key": "value"}')
    file2.write_text("處理結果\n")
    
    # 列出所有檔案
    files = list(Path(tmpdir).iterdir())
    print(f"📄 建立了 {len(files)} 個檔案:")
    for f in files:
        print(f"  - {f.name}")
    
    print(f"\n✅ 資料夾存在: {os.path.exists(tmpdir)}")

# 🔥 離開後自動刪除整個資料夾
print(f"❌ 資料夾已刪除: {not os.path.exists(tmpdir)}")

輸出:

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

4️⃣ TemporaryFile:無名臨時檔案
TemporaryFile 建立的檔案沒有可見檔名
(在 Unix 系統上會立即從檔案系統 unlink),
適合純粹的暫存資料處理。

# 無名臨時檔案適合資料暫存
with tempfile.TemporaryFile(mode='w+') as tmp:
    # ⚠️ 沒有 .name 屬性或為空
    print(f"檔案物件: {tmp}")
    
    # 寫入大量資料
    for i in range(100):
        tmp.write(f"資料行 {i}\n")
    
    # 移回開頭讀取
    tmp.seek(0)
    first_line = tmp.readline()
    print(f"📖 第一行: {first_line.strip()}")
    
    # 跳到結尾查看大小
    tmp.seek(0, 2)
    size = tmp.tell()
    print(f"📊 總大小: {size} bytes")

# 離開後自動刪除無殘留
print("✅ 檔案已自動清理")

輸出:

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

5️⃣ mkstemp / mkdtemp:低階控制
這兩個函式提供更底層的控制,
回傳檔案描述符(file descriptor)而非檔案物件,
適合需要精細控制的場景。

⚠️ 重要:這些函式不會自動清理,必須手動刪除!

範例 5.1:mkstemp

# %%
# mkstemp檔案描述符 + 路徑
fd, tmp_path = tempfile.mkstemp(suffix='.csv', prefix='export_')
print(f"📝 檔案描述符: {fd}")
print(f"📂 檔案路徑: {tmp_path}")

try:
    # 透過檔案描述符寫入低階 I/O
    os.write(fd, b"Name,Age\n")
    os.write(fd, b"Alice,30\n")
    os.write(fd, b"Bob,25\n")
    
    # 關閉檔案描述符
    os.close(fd)
    
    # 確認檔案內容
    with open(tmp_path, 'r') as f:
        print(f"\n📊 CSV 內容:\n{f.read()}")
finally:
    # 🔥 必須手動刪除
    if os.path.exists(tmp_path):
        os.remove(tmp_path)
        print("✅ 已清理臨時檔案")

輸出:

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

範例 5.2:mkdtemp

# %%
# mkdtemp臨時資料夾
tmpdir = tempfile.mkdtemp(prefix='backup_')
print(f"📁 臨時資料夾: {tmpdir}")

try:
    # 建立多個檔案
    (Path(tmpdir) / "file1.txt").write_text("資料 1")
    (Path(tmpdir) / "file2.txt").write_text("資料 2")
    
    files = list(Path(tmpdir).iterdir())
    print(f"📄 建立 {len(files)} 個檔案")
    
finally:
    # 🔥 手動刪除整個資料夾
    shutil.rmtree(tmpdir)
    print("✅ 已清理臨時資料夾")

輸出:

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

6️⃣ 生命週期管理與最佳實踐
選擇指南

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

異常處理範例

def process_with_temp_file():
    """模擬可能失敗的處理流程"""
    tmp = tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False)
    
    try:
        tmp.write('{"status": "processing"}')
        tmp.flush()
        print(f"✅ 臨時檔案建立: {tmp.name}")
        
        # 模擬處理可能拋出異常
        # raise ValueError("模擬錯誤")  # 取消註解測試異常處理
        
        tmp.write('\n{"status": "completed"}')
        tmp.flush()
        print("✅ 處理完成")
        
    except Exception as e:
        print(f"❌ 錯誤: {e}")
        raise
    
    finally:
        tmp.close()
        # 確保清理即使發生異常
        if os.path.exists(tmp.name):
            os.remove(tmp.name)
            print("🗑️ 臨時檔案已清理")

# 執行
process_with_temp_file()

輸出:

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

7️⃣ 實戰案例:安全處理 DOCX 檔案

這個範例展示如何使用 tempfile 安全地處理 Word 文件,
避免直接修改原始檔案。

import tempfile
import shutil
import os
from pathlib import Path

def safe_modify_document(source_path: str, output_path: str):
    """安全修改文件的完整流程(修正編碼問題)"""
    
    # 步驟 1:建立臨時複製
    with tempfile.NamedTemporaryFile(suffix='.txt', delete=False) as tmp:
        tmp_path = tmp.name
    
    try:
        print(f"📋 原始檔案: {source_path}")
        print(f"⚙️ 臨時檔案: {tmp_path}")
        
        # 複製到臨時位置
        shutil.copy2(source_path, tmp_path)
        print("✅ 已複製到臨時位置")
        
        # 步驟 2:修改臨時檔案明確指定 UTF-8)
        with open(tmp_path, 'a', encoding='utf-8') as f:
            f.write("\n--- 新增內容 ---\n")
            f.write("這是在臨時檔案中新增的資料\n")
        print("✅ 已修改臨時檔案")
        
        # 步驟 3:移動到最終位置原子操作
        shutil.move(tmp_path, output_path)
        print(f"✅ 已儲存到: {output_path}")
        
    except Exception as e:
        print(f"❌ 處理失敗: {e}")
        # 清理臨時檔
        if os.path.exists(tmp_path):
            os.remove(tmp_path)
        raise
    
    finally:
        # 確保清理 move 成功tmp_path 已不存在
        if os.path.exists(tmp_path):
            os.remove(tmp_path)

# 建立測試檔案明確指定 UTF-8)
test_source = Path(tempfile.gettempdir()) / "test_input.txt"
test_source.write_text("原始內容\n第一行\n第二行\n", encoding='utf-8')

# 執行安全修改
test_output = Path(tempfile.gettempdir()) / "test_output.txt"
safe_modify_document(str(test_source), str(test_output))

# 驗證結果明確指定 UTF-8)
print(f"\n📖 最終內容:\n{test_output.read_text(encoding='utf-8')}")

# 清理
test_source.unlink()
test_output.unlink()

輸出:

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

🎯 總結與對照表

tempfile vs 手動管理

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

常見錯誤與修正

❌ 錯誤 1:忘記 flush

with tempfile.NamedTemporaryFile(delete=False) as tmp:
    tmp.write(b"data") #替換成自己要的bytes data
    # ❌ 沒有 flush資料可能在緩衝區
    with open(tmp.name,"rb") as f:
        print(f.read())  # 可能讀不到

✅ 正確做法

with tempfile.NamedTemporaryFile(delete=False) as tmp:
    tmp.write(b"data")
    tmp.flush()  # ✅ 強制寫入磁碟

輸出:

Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

❌ 錯誤 2:Windows 檔案鎖定

with tempfile.NamedTemporaryFile(delete=True) as tmp:
    tmp.write(b"data")
    with open(tmp.name, 'rb') as f:  # ❌ Windows 上會失敗
        print(f.read())

✅ 正確做法

with tempfile.NamedTemporaryFile(delete=False) as tmp:
    tmp.write(b"data")
    tmp.close()  # ✅ 關閉後再開
    with open(tmp.name, 'rb') as f:
        print(f.read())
os.remove(tmp.name)

推薦hahow線上學習python: https://igrape.net/30afN

加入好友
加入社群
Python tempfile 模組完全指南:安全管理臨時檔案的最佳實踐; import tempfile ; tempfile.gettempdir() ; tempfile.template ; os.access(temp_dir, os.W_OK) ; with tempfile.NamedTemporaryFile() as tmp #有檔名的臨時檔案 ; with tempfile.TemporaryDirectory() as tmpdir #臨時資料夾 ; with tempfile.TemporaryFile() as tmp #無檔名的臨時檔案 - 儲蓄保險王

儲蓄保險王

儲蓄險是板主最喜愛的儲蓄工具,最喜愛的投資理財工具則是ETF,最喜愛的省錢工具則是信用卡

You may also like...

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *