satumaimoの備忘録

個人的なメモ中心

【Python】os._exit()で終了するプログラムではファイルを書き出す時にflushする

はじめに

os._exit()を使用するPythonプログラムでは,ファイルへ書き込まれたデータがユーザランドのバッファからOSに移る前にプロセスが終了する場合があります.

この場合,プログラムで行ったはずのファイルへの書き込みは,実際のファイルシステムには反映されません.

このような問題は,flushを行えば解決できます.

例1:一般的なファイル書き込み

以下のプログラムを考えます.

import os

with open("hoge.txt", 'w') as f:
    f.write("hoge")
    os._exit(0)

(環境次第ですが)上記プログラムを実行しても,hoge.txtに文字列hogeは書き込まれません.

このとき,flush()を用いれば文字列hogeが書き込めるようになります.

import os

with open("hoge.txt", 'w') as f:
    f.write("hoge")
    f.flush()           # バッファ内のデータをOSに渡す
    os._exit(0)

Pythonclose()はflushを行う処理も含んでいるようなので,以下のコードでも文字列hogeが書き込まれます.

import os

with open("hoge.txt", 'w') as f:
    f.write("hoge")
os._exit(0)

例2:標準出力のリダイレクト

個人的な本題はこちらです.

以下のプログラムを考えます.

import os

print("hoge")

os._exit(0)

リダイレクトを指定せずにこのプログラムを実行した場合,文字列hogeはターミナルに問題なく出力されます.

しかし,以下のようにリダイレクト先にファイルを指定した場合,文字列hogeは出力されません.

$ python3 hoge.py | tee hoge.txt
(出力なし)

この場合は,sys.stdout.flush()を呼び出すとリダイレクト先に標準出力がflushされます.

import os
import sys

print("hoge")
sys.stdout.flush()

os._exit(0)

おわりに

「標準出力をリダイレクトすると出力されなくなる/出力が途中で終わる」という問題を,flushを関連付けて言及している記事が見つからなかったので,このような記事を書きました.

Pythonでやむを得ずos._exit()を呼び出す場合は,flushを意識してプログラムを書く必要がありそうです.

参考文献

雑多なオペレーティングシステムインターフェース — Python 3.11.3 ドキュメント

ファイルオブジェクトのcloseはflushも行う。確実にしたければfsync - 静かなる名辞