Apa sebenarnya yang dilakukan file.flush () Python?

143

Saya menemukan ini di dokumentasi Python untuk File Objects :

flush () tidak selalu menulis data file ke disk. Gunakan flush () diikuti oleh os.fsync () untuk memastikan perilaku ini.

Jadi pertanyaan saya adalah: apa sebenarnya yang dilakukan Python flush? Saya pikir itu memaksa untuk menulis data ke disk, tetapi sekarang saya melihat itu tidak terjadi. Mengapa?

kutu buku
sumber

Jawaban:

227

Biasanya ada dua tingkat buffering yang terlibat:

  1. Buffer internal
  2. Buffer sistem operasi

Buffer internal adalah buffer yang dibuat oleh runtime / library / bahasa tempat Anda memprogram dan dimaksudkan untuk mempercepat dengan menghindari panggilan sistem untuk setiap penulisan. Sebaliknya, saat Anda menulis ke objek file, Anda menulis ke buffernya, dan setiap kali buffer terisi, data ditulis ke file sebenarnya menggunakan panggilan sistem.

Namun, karena buffer sistem operasi, ini mungkin tidak berarti bahwa data ditulis ke disk . Ini mungkin berarti bahwa data disalin dari buffer yang dikelola oleh runtime Anda ke buffer yang dikelola oleh sistem operasi.

Jika Anda menulis sesuatu, dan berakhir di buffer (hanya), dan daya diputus ke mesin Anda, data itu tidak ada di disk saat mesin dimatikan.

Jadi, untuk membantu itu Anda memiliki flushdan fsyncmetode, pada objek masing-masing.

Yang pertama,, flushhanya akan menulis data apa pun yang tertinggal dalam buffer program ke file sebenarnya. Biasanya ini berarti bahwa data akan disalin dari buffer program ke buffer sistem operasi.

Secara khusus, ini berarti bahwa jika proses lain memiliki file yang sama terbuka untuk dibaca, itu akan dapat mengakses data yang baru saja Anda masukkan ke file. Namun, itu tidak berarti telah disimpan "secara permanen" di disk.

Untuk melakukan itu, Anda perlu memanggil os.fsyncmetode yang memastikan semua buffer sistem operasi disinkronkan dengan perangkat penyimpanan tempatnya, dengan kata lain, metode tersebut akan menyalin data dari buffer sistem operasi ke disk.

Biasanya Anda tidak perlu repot dengan metode mana pun, tetapi jika Anda berada dalam skenario di mana paranoia tentang apa yang sebenarnya berakhir di disk adalah hal yang baik, Anda harus membuat kedua panggilan seperti yang diinstruksikan.


Adendum tahun 2018.

Perhatikan bahwa disk dengan mekanisme cache sekarang jauh lebih umum daripada sebelumnya di tahun 2013, jadi sekarang ada lebih banyak level cache dan buffer yang terlibat. Saya berasumsi buffer ini akan ditangani oleh panggilan sync / flush juga, tapi saya tidak begitu tahu.

Lasse V. Karlsen
sumber
10
Ketika saya menggunakan with file('blah') as fd: #dostuffkonstruksi, saya tahu itu menjamin penutupan deskriptor file. Apakah itu juga flush atau sync?
Marcin
3
@Marcin: Ini memerah, tapi TIDAK sinkron.
Alex I
8
fsyncdiperlukan untuk atomicity. Anda tidak dapat menutup file, membukanya kembali, dan menemukan konten Anda tanpa fsyncdi tengah. Ini sering berfungsi, tetapi tidak di linux dengan ext4 dan opsi pemasangan default misalnya. Juga fsynctidak dijamin untuk benar-benar membalik magnet besi di piring, karena 1: fsync dapat dinonaktifkan (dengan mode laptop), dan 2: penyangga internal hard disk mungkin tidak diinstruksikan untuk mengosongkan.
v.oddou
1
apakah ada cara untuk membersihkan buffer sistem operasi untuk semua file, jika file tersebut ditulis oleh proses lain?
Nacht
1
fsync relatif mahal. Secara umum, Anda tidak menulis perangkat lunak misi penting yang membutuhkan kepatuhan dan ketahanan ACID 100% untuk akses disk, dan jika Anda melakukannya, Anda mungkin sangat menyadarinya dan harus mengetahui langkah-langkah yang dapat Anda ambil untuk mendapatkan jaminan ini. . Memanggil fsync akan menunggu akses disk fisik terjadi untuk menulis data ke disk, sedangkan pembilasan dan penutupan hanya akan menunggu data dipindahkan ke memori cache. Perbedaan kecepatan mungkin beberapa kali lipat.
Lasse V. Karlsen
10

Karena sistem operasi mungkin tidak melakukannya. Operasi pembilasan memaksa data file ke dalam cache file di RAM, dan dari sana tugas OS untuk benar-benar mengirimkannya ke disk.

Ignacio Vazquez-Abrams
sumber
6
Anda benar, tetapi actuallyrelatif di sini: jika perangkat target mengaktifkan cache tulis, data mungkin tidak mencapai piringan / chip yang sebenarnya saat os.fsync()dikembalikan.
Frédéric Hamidi
7

Ini membersihkan buffer internal, yang seharusnya menyebabkan OS menulis buffer ke file. [1] Python menggunakan buffering default OS kecuali Anda mengkonfigurasinya untuk melakukan sebaliknya.

Namun terkadang OS masih memilih untuk tidak bekerjasama. Terutama dengan hal-hal luar biasa seperti penundaan penulisan di Windows / NTFS. Pada dasarnya buffer internal dibilas, tetapi buffer OS masih memegangnya. Jadi, Anda harus memberi tahu OS untuk menuliskannya ke disk os.fsync()dalam kasus tersebut.

[1] http://docs.python.org/library/stdtypes.html

Dan
sumber
0

Pada dasarnya, flush () membersihkan buffer RAM Anda, kekuatan sebenarnya adalah memungkinkan Anda terus menulis ke sana setelahnya - tetapi tidak boleh dianggap sebagai fitur tulis ke file terbaik / teraman. Itu menguras RAM Anda untuk lebih banyak data yang akan datang, itu saja. Jika Anda ingin memastikan data ditulis ke file dengan aman, gunakan close () sebagai gantinya.

zA.
sumber