テクノロジー · 実用ガイド
Python SpooledTemporaryFileがディスク化・空読み?rolloverと位置を監査
libraryやsubprocessへ渡す前に、隠れたfileno rolloverとEOF位置を分離します。

SpooledTemporaryFileには別々の落とし穴があります。consumerのfileno()で小さなpayloadもdiskへ移り、write後のEOF位置では下流が空を読みます。
public APIだけでtriggerを特定し、handoff前にseek(0)、bytesかdescriptorかを決め、real consumerでdeliveryとstorage policyを検証します。
1. storage stateとstream positionを分ける
consumerへ渡すobject、max_size、write bytes、tell()、fileno() callを記録します。memoryのままEOF、disk上でも同じEOFという別状態があります。
privateな_fileや_rolledをcontractにせず、隔離testでtemp directoryを観測し、所有するconsumer boundaryだけをwrapします。
2. rollover triggerを特定する
Pythonのtriggerは非zero max_size超過、fileno()、明示rollover()です。current CPythonのdefault 0はsize triggerを無効にしますが、後二つはdisk化します。
実際のlibrary/framework/subprocessを監査します。descriptor-only APIは隠れてfileno()を呼べるため、no-disk policyとは両立しません。
3. handoff前にpublic cursorを戻す
write後、次のreader前にseek(0)します。CPython issueのempty stdinはcursorがendにあったためで、object不良ではありません。rolloverはrewindしません。
FastAPI UploadFileのasync codeではawait upload.seek(0)を使い、syncではpublic file methodとfinal close ownerを明記します。
4. handoff contractを一つ選ぶ
consumerがbytesを受けるならpipe、BytesIO、read resultでno-diskを保てます。real descriptor必須なら明示rollover、temp space確認、seek(0)、handoff、owner closeを一つのcontractにします。
durable outputはcaller指定先へcopyし、必要ならfsync/atomic replaceを定義します。temporary fileは永続化interfaceではありません。
5. real boundaryで二軸を試験する
distinct payloadを書き、tell()、rewind、real consumer、exact resultを確認し、below-thresholdとforced-rolloverを実行します。
fileno()を記録するtest doubleと隔離temp directory観測を追加し、delivery、storage policy、close cleanupを別々にassertします。
