科技 · 實用指南
NamedTemporaryFile 在 POSIX 正常、Windows 失敗?先選重開與刪除合約
暫存路徑有三位責任人:建立者、第二次開啟者與清理者。交出名稱前先決定哪個控制代碼保持開啟。

NamedTemporaryFile 提供可見路徑,但不保證每個第二控制代碼都能重開、重新命名或刪除。POSIX 可在原控制代碼開啟時再開;Windows 會核對所有現有控制代碼的存取與共用模式。
建立前先選生命週期合約:消費者取得已關閉路徑、在建立者仍開啟時重開,還是負責最後清理?再把 delete 與 delete_on_close 綁定,離開 context 前關閉不相容控制代碼,並驗證消費與刪除結果。
先寫下一位擁有者
Write down whether the next user is the same Python handle, a second Python open, a library that accepts a path, or an external process. Also state whether that consumer needs only read/write access or may rename, replace, or keep the file mapped.
If the consumer accepts a file object, prefer passing the existing object and avoid a second pathname open. If it requires a path, the handle and cleanup contract must be explicit.
選擇生命週期合約
For same-context reopen on Python 3.12+, delete=True with delete_on_close=False keeps automatic context-exit cleanup while allowing an ordinary second open on Windows. Close that second handle before leaving the context.
For an external process or API that cannot share delete access, flush and close the producer, use delete=False, pass the path, wait for the consumer, then remove the file in finally. For a specialized second Python open that shares delete access, use the documented O_TEMPORARY route only when every participant follows the same contract.
分開 flush、close 與程序結束
flush makes Python buffers visible but does not release the Windows handle or its share-mode record. close releases that handle. Waiting for the subprocess proves only that process exit occurred; it does not prove another library or mapped view released the file.
Keep the producer, consumer, and cleanup timestamps in a small ledger. A cleanup PermissionError is evidence of an outstanding handle or missing delete right, not a reason to silently leak the path.
把重新命名與刪除視為獨立存取
Microsoft documents that delete access includes rename. A file can be readable and writable yet still reject os.replace, fileinput in-place editing, or cleanup because a prior handle did not share delete access.
Do not diagnose every WinError 32 as another process. Record the exact operation, every handle you own, whether each is closed, and whether the consumer might retain a mapping.
在兩個平台驗證
Create a fixture that writes bytes, reopens or hands off the path exactly as production does, confirms the consumer read the expected hash, closes every handle, exits the context, and asserts whether the path should exist. Run it on Windows and POSIX.
For delete=False, assert deletion in finally and fail loudly if removal fails. For delete_on_close=False, assert the second handle closes before context exit. Also test the exception path so cleanup is not dependent on a successful consumer.
