open
したものはclose
しましょう。
質問文みたいになる理由の説明。
処理系の実装、OS側でのバッファリングなどに依存する話だし、いろいろな背景知識がないとわからないので、あまり深く考えない方が良いのですが……
まず前提として、ファイルにwrite
したタイミング(csv.writer
を介しても同じこと)でファイルへの書き込みが完了する訳ではありません。内部的に都合のいいタイミングで書き込まれるんです。
close
する、あるいは単にflush
することで、そのタイミングで書き出すことをほぼ強制できます(close
したときにはflush
がファイルを閉じる前に呼ばれます。また、close
したとしてもOS側で行われるバッファリングによってタイミングのズレは生じる可能性があります。拙記事:ファイルオブジェクトのcloseはflushも行う。確実にしたければfsync - 静かなる名辞)。
以上を踏まえて、コードを見ていきましょう。
まずこの部分について。
python
1import csv
2import time
3
4lists = ["red", "blue", "yellow"]
5for i in lists:
6 csv_file = open('color.csv', 'a+', newline='')
7 writer = csv.writer(csv_file)
8 writer.writerow(i)
9 print(i + "ファイル投入完了")
10 time.sleep(3)
csv_file
, writer
という変数名を毎回使いまわしていますね。ということは、"red"
のときと"blue"
のときのファイルオブジェクト(型としては_io.TextIOWrapper)
、csv.writer
オブジェクトは他に参照している変数がないので、再代入のタイミングで参照カウントが0になり、メモリ上から消滅します。
といってもいきなり消滅する訳ではなく、オブジェクト固有のメモリ上から消える前に行われる処理があります(いわゆるデストラクタ)。ここでclose
が呼ばれる実装になっているので、このタイミングで書き出されます。
明示的にファイルを閉じなかった場合は、いつかは Python のガベージコレクタがそのファイルオブジェクトを破棄し開かれいていたファイルを閉じますが、しばらくはファイルが開かれたままでいる可能性があります。
7. 入力と出力 — Python 3.7.4 ドキュメント | 7.2. ファイルを読み書きする
で、よくよく考えてみてほしいのですが、"yellow"
のときに最後に代入されたファイルオブジェクト
とcsv.writer
オブジェクトは、特に再代入されないので、そのまま残ります。
なので、ファイルは「開きっぱなし」です。そのまま下の部分が実行されます。
python
1fn = 'color.csv'
2
3with open(fn, "r") as f:
4 s = f.read()
この下でprint(s)
とかやるとわかりますが、"y,e,l,l,o,w"
は書き込まれていません。これはバッファリングされていて、そのうち書き込まれるというものです。この状態で
python
1s = s.replace("r,e,d","赤")
2s = s.replace("b,l,u,e","青")
3s = s.replace("y,e,l,l,o,w","黄色")
4
5with open(fn, "w") as f:
6 f.write(s)
7
が実行されますが、"y,e,l,l,o,w"
なんて最初からないので、ファイルの中身は
になります。
これですべての処理が終わってPythonプロセスが正常終了するのですが、その前に残っているオブジェクトはすべて破棄され、ここでデストラクタが呼ばれます。「開きっぱなし」にしていたファイルオブジェクトも破棄され、そこでデストラクタが呼ばれるのでやっと"y,e,l,l,o,w"
が書き込まれる。
……という流れです。
ついでに。
文字列の書き込みならcsv.writer
を使う必要はありません。というか使うだけ無駄です。f.write(string + "\n")
とかしてください。
ループが回る度にファイルを開き直すと効率と見た目が悪いです。普通はループの外で開くでしょう。
python
1lst = ["red", "blue", "yellow"]
2filename = "color.csv"
3with open(filename, "w") as f:
4 for x in lst:
5 f.write(x + "\n")
6
書きたいものが赤青黄色なら最初からこの3行を書けば良いので、上の処理は必要ありません。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/08/11 20:47
2019/08/11 21:54