#追記(2021.02.18)
早速ですが、嘘書いたので訂正します。
#Pythonでファイル操作するときにflushを書く理由
##flushって何?
ファイルへの書き込みを実行します。
##flushっていつ使うの?
ファイル操作するときに、読み書きしますね。
その時、withを使って操作するのがPythonでは一般的でしょう。
with open("hoge.txt", 'r') as f:
print(f.read())
こんな感じです。
withは優秀なので、ファイルクローズし忘れという大罪を防いでくれます。
withを使わないで書くなら、こうなります。
f = open("hoge.txt", 'r') as f:
print(f.read())
f.close()
最後に必ず、closeを書く必要があります。
これ書かないと、pythonがずっとファイルを握っちゃいます(たぶん)。
さて、ただファイルを読み書きするだけならwithだけで問題ないのです。
しかし、同一のファイルを複数の処理からアクセスするときにflushが必要になります。
そもそも、flushはファイルがクローズされるときに勝手に実行されるため、普段は明示的に書いて上げる必要はありません。
ですが、例えば、次のような場合を考えてみてください。
def read1():
with open("hoge.txt", 'r') as f:
print(f.read())
def read2():
with open("hoge.txt" , 'w') as f:
f.write("hoge")
read1()
これは、read2でhoge.txtにhogeと書き込んで、read1でhoge.txtの中身を参照しようとしています。
read2を実行すると、出力結果はどうなるでしょうか。。。
答え:(出力なし)
です。
ぱっと見た感じ、問題なくhogeと出力されそうですよね。
ですが、アベンドもしないし、想定した出力も出ません。
この問題の重要な点は、__「いつcloseが呼ばれるか」__です。
f.writeで書き込んだはずのhogeですが、これがhoge.txtに書き込まれるタイミングは、withのスコープが終了したとき時と場合によるです。
つまり、ココです。
def read1():
with open("hoge.txt", 'r') as f:
print(f.read())
def read2():
with open("hoge.txt" , 'w') as f:
f.write("hoge")
read1()
# ココ!!(2021.02.18追記:嘘でした、ごめんなさい。)
# 実際は、スコープを抜けても書き込まれてるかは、運次第です。
ということは、read2のwithのスコープが終了する前にread1で読み込んだhoge.txtには、まだhogeが書き込まれていないのです!
では、read2のwithスコープ内で書き込んだ内容を読み込むには、スコープを一旦抜けないといけないのでしょうか。
writeで書き込もうとしたデータは、一度ファイルバッファという場所に保管され、いつ書き込まれるかは、わかりません。
さっさと書き込まれる事もあれば、そうでないときもあります。
自分のタイミングで書き込んでほしい!
そこで、flushの登場です。
flushはcloseされるときに自動で呼ばれますが、自分で明示的に書いても問題ありません。
なので、こう書けば丸く収まります。
def read1():
with open("hoge.txt", 'r') as f:
print(f.read())
def read2():
with open("hoge.txt" , 'w') as f:
f.write("hoge")
f.flush() # ←ここでflush!!
read1()
これで、無事hogeが出力されるようになりました。
hoge
##まとめ
今回取り上げた例は、わかりやすさのために、かなり極端な例を挙げました。
ですが、同じファイルに複数の処理からアクセスする場面は多くあるでしょう。
そういったときに問題なのが、「アベンドしないけど、出力結果がおかしい!」という場合です。
なので、私的には、flushはなるたけ書いとく、という結論に至りました。
もちろん、一つの処理でしか読み書きしないなら、不要なコードなので書く必要は皆無ですが、便利機能を使いすぎてると
ついつい書き込みタイミングとかの意識が薄れてしまいがちなので、意識付けのためにも書こうかなーと思ってます。