Co dokładnie robi file.flush () w Pythonie?

137

Znalazłem to w dokumentacji Pythona dla obiektów plików :

flush () niekoniecznie zapisuje dane pliku na dysk. Użyj flush (), a następnie os.fsync (), aby zapewnić takie zachowanie.

Moje pytanie brzmi: co dokładnie flushrobi Python ? Myślałem, że wymusza zapisywanie danych na dysku, ale teraz widzę, że tak nie jest. Czemu?

maniak
źródło

Odpowiedzi:

219

Zazwyczaj występują dwa poziomy buforowania:

  1. Bufory wewnętrzne
  2. Bufory systemu operacyjnego

Bufory wewnętrzne to bufory utworzone przez środowisko wykonawcze / bibliotekę / język, w odniesieniu do których programujesz, i mają na celu przyspieszenie działania poprzez unikanie wywołań systemowych przy każdym zapisie. Zamiast tego, kiedy piszesz do obiektu pliku, zapisujesz do jego bufora, a gdy bufor się zapełnia, dane są zapisywane do właściwego pliku za pomocą wywołań systemowych.

Jednak ze względu na bufory systemu operacyjnego może to nie oznaczać, że dane są zapisywane na dysku . Może to po prostu oznaczać, że dane są kopiowane z buforów utrzymywanych przez środowisko wykonawcze do buforów obsługiwanych przez system operacyjny.

Jeśli coś napiszesz i skończy się to w buforze (tylko), a zasilanie zostanie odcięte, dane nie będą znajdować się na dysku, gdy maszyna się wyłączy.

Tak, aby pomóc z tym masz flushi fsyncmetod, na swoich obiektach.

Pierwszy, flushpo prostu zapisze wszelkie dane, które pozostają w buforze programu, do właściwego pliku. Zwykle oznacza to, że dane zostaną skopiowane z bufora programu do bufora systemu operacyjnego.

W szczególności oznacza to, że jeśli inny proces ma ten sam plik otwarty do odczytu, będzie mógł uzyskać dostęp do danych, które właśnie przesłałeś do pliku. Jednak nie musi to oznaczać, że został on „trwale” zapisany na dysku.

Aby to zrobić, musisz wywołać os.fsyncmetodę, która zapewnia, że ​​wszystkie bufory systemu operacyjnego są zsynchronizowane z urządzeniami pamięci masowej, dla których są przeznaczone, innymi słowy, ta metoda skopiuje dane z buforów systemu operacyjnego na dysk.

Zazwyczaj nie musisz zawracać sobie głowy żadną metodą, ale jeśli jesteś w scenariuszu, w którym paranoja dotycząca tego, co faktycznie trafia na dysk, jest dobrą rzeczą, powinieneś wykonać oba połączenia zgodnie z instrukcją.


Uzupełnienie w 2018 r.

Zauważ, że dyski z mechanizmami pamięci podręcznej są teraz znacznie bardziej powszechne niż w 2013 roku, więc teraz jest zaangażowanych jeszcze więcej poziomów buforowania i buforów. Zakładam , że te bufory będą również obsługiwane przez wywołania sync / flush, ale tak naprawdę nie wiem.

Lasse V. Karlsen
źródło
10
Kiedy używam with file('blah') as fd: #dostuffkonstrukcji, wiem, że gwarantuje ona zamknięcie deskryptora pliku. Czy również opróżnia lub synchronizuje?
Marcin
3
@Marcin: Opróżnia, ale NIE synchronizuje.
Alex I
8
fsyncjest niezbędna dla atomowości. nie możesz oczekiwać, że zamkniesz plik, otworzysz go ponownie i znajdziesz zawartość bez fsyncpośrodku. Często działa, ale nie działa na Linuksie z na przykład ext4 i domyślnymi opcjami montowania. Nie fsyncma również gwarancji, że naprawdę magnetycznie odwrócisz żelazko na talerzach, ponieważ 1: fsync można wyłączyć (w trybie laptopa), a 2: wewnętrzne buforowanie dysku twardego może nie zostać poinstruowane, aby opróżnić.
v.oddou,
1
czy istnieje sposób na opróżnienie bufora systemu operacyjnego dla wszystkich plików, jeśli plik jest zapisywany przez inny proces?
Nacht
1
fsync jest stosunkowo drogi. Ogólnie rzecz biorąc, nie piszesz oprogramowania o znaczeniu krytycznym, które wymaga 100% zgodności z ACID i trwałości w celu uzyskania dostępu do dysku, a jeśli tak, prawdopodobnie jesteś tego świadomy i powinieneś być świadomy kroków, które możesz podjąć, aby uzyskać te gwarancje . Wywołanie fsync będzie czekać na dostęp do dysku fizycznego, aby zapisać dane na dysku, podczas gdy opróżnianie i zamykanie będzie tylko czekać na przeniesienie danych do pamięci podręcznej. Różnica prędkości wynosi prawdopodobnie kilka rzędów wielkości.
Lasse V. Karlsen
10

Ponieważ system operacyjny może tego nie robić. Operacja opróżniania wymusza zapisanie danych pliku do pamięci podręcznej plików w pamięci RAM, a stamtąd zadaniem systemu operacyjnego jest wysłanie ich na dysk.

Ignacio Vazquez-Abrams
źródło
6
Masz rację, ale actuallyjest to względne: jeśli urządzenie docelowe ma włączone buforowanie zapisu, dane mogą nie osiągnąć rzeczywistych talerzy / chipów po os.fsync()powrocie.
Frédéric Hamidi
7

Opróżnia bufor wewnętrzny, co ma spowodować, że system operacyjny wypisze bufor do pliku. [1] Python używa domyślnego buforowania systemu operacyjnego, chyba że skonfigurujesz go inaczej.

Ale czasami system operacyjny nadal nie chce współpracować. Zwłaszcza w przypadku wspaniałych rzeczy, takich jak opóźnienia zapisu w systemie Windows / NTFS. Zasadniczo bufor wewnętrzny jest opróżniany, ale bufor systemu operacyjnego nadal go utrzymuje. Musisz więc powiedzieć systemowi operacyjnemu, aby zapisał go na dysku os.fsync()w takich przypadkach.

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

Dan
źródło
0

Zasadniczo flush () czyści bufor pamięci RAM, jego prawdziwą mocą jest to, że umożliwia dalsze zapisywanie w nim później - ale nie należy go uważać za najlepszą / najbezpieczniejszą funkcję zapisu do pliku. To opróżnianie pamięci RAM, aby uzyskać więcej danych, to wszystko. Jeśli chcesz mieć pewność, że dane zostaną bezpiecznie zapisane do pliku, użyj zamiast tego close ().

zA.
źródło