為什麼需要 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/...輸出:

- 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,針對目前有效使用者/群組判斷,
實際開檔仍應處理例外。

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

範例 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)}")輸出:

範例 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)}")輸出:

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)}")輸出:

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("✅ 檔案已自動清理")輸出:

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("✅ 已清理臨時檔案")輸出:

範例 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("✅ 已清理臨時資料夾")輸出:

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

異常處理範例
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()輸出:

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()輸出:

🎯 總結與對照表
tempfile vs 手動管理

常見錯誤與修正
❌ 錯誤 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() # ✅ 強制寫入磁碟輸出:

❌ 錯誤 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 檢驗字符串格式:掌握正則表達式(Regular Expression)的起始^與終止$符號, pattern = r’^GATR[0-9]{4}$’ 使用 Python 檢驗字符串格式:掌握正則表達式(Regular Expression)的起始^與終止$符號, pattern = r’^GATR[0-9]{4}$’](https://i0.wp.com/savingking.com.tw/wp-content/uploads/2024/07/20240712093637_0.png?quality=90&zoom=2&ssl=1&resize=350%2C233)






近期留言