Що саме робить файл file.flush () Python?


137

Я знайшов це в документації Python для файлових об’єктів :

flush () не обов'язково записує дані файлу на диск. Використовуйте flush (), за яким слідує os.fsync (), щоб забезпечити цю поведінку.

Отже, моє запитання: що саме робить Python flush? Я думав, що це змушує записувати дані на диск, але тепер я бачу, що це не так. Чому?

Відповіді:


220

Зазвичай передбачається два рівні буферизації:

  1. Внутрішні буфери
  2. Буфери операційної системи

Внутрішні буфери - це буфери, створені програмою виконання / бібліотекою / мовою, проти якої ви програмуєте, і призначені для прискорення роботи, уникаючи системних викликів для кожного запису. Натомість, коли ви пишете в файл-об’єкт, ви записуєте його в буфер, і коли буфер заповнюється, дані записуються у фактичний файл за допомогою системних викликів.

Однак через буфери операційної системи це може не означати, що дані записуються на диск . Це може просто означати, що дані копіюються з буферів, що підтримуються під час виконання, у буфери, що підтримуються операційною системою.

Якщо ви щось пишете, і це закінчується в буфері (тільки), і живлення відключається на вашій машині, дані не знаходяться на диску, коли машина вимикається.

Отже, для того, щоб допомогти в цьому, ви маєте свої методи flushта fsyncметоди їх відповідних об'єктів.

По-перше, flushпросто випишуть будь-які дані, які зберігаються в програмному буфері до фактичного файлу. Зазвичай це означає, що дані будуть скопійовані з програмного буфера в буфер операційної системи.

Зокрема, це означає, що якщо в іншому процесі цей самий файл відкритий для читання, він зможе отримати доступ до даних, які ви тільки що передали у файл. Однак це не обов'язково означає, що він був "назавжди" збережений на диску.

Для цього вам потрібно викликати os.fsyncметод, який забезпечує всі буфери операційної системи синхронізовані з накопичувачами, для яких вони є, іншими словами, цей метод буде копіювати дані з буферів операційної системи на диск.

Зазвичай вам не потрібно зациклюватися на будь-якому методі, але якщо у вас є сценарій, коли параноїя щодо того, що насправді закінчується на диску, є хорошою справою, вам слід робити обидва дзвінки за інструкцією.


Додаток 2018 року.

Зауважте, що диски з механізмами кешування зараз набагато частіше, ніж у 2013 році, тому зараз є ще більше рівнів кешування та буферів. Я припускаю, що з цими буферами також буде оброблятися синхронізація / змивання дзвінків, але я не знаю насправді.


10
Коли я використовую with file('blah') as fd: #dostuffконструкцію, я знаю, що це гарантує закриття дескриптора файлів. Це також промиває чи синхронізує?
Марцін

3
@Marcin: миє, але НЕ синхронізується.
Олексій І

8
fsyncнеобхідний для атомності. ви не можете розраховувати закрити файл, знову відкрити його і знайти вміст без fsyncсередини. Він часто працює, але, наприклад, не працює на Linux з ext4 та параметрами монтажу за замовчуванням. Також fsyncне гарантується дійсно магніт перевернути залізо на тарілках, тому що 1: fsync можна відключити (у режимі ноутбука), а 2: внутрішнє буферизація жорсткого диска може бути не вказується промивати.
v.oddou

1
чи є можливість промити буфер операційної системи для всіх файлів, якщо файл записаний іншим процесом?
Нахт

1
fsync відносно дорогий. Загалом, ви не пишете найважливіше програмне забезпечення, яке потребує 100% відповідності ACID та довговічності для доступу до диска, і якщо ви це зробите, ви, мабуть, про це усвідомлюєте, і вам слід знати, які кроки можна зробити, щоб отримати ці гарантії . Виклик fsync зачекає появи фізичного диска для запису даних на диск, тоді як промивання та закриття очікує лише переміщення даних у кеш-пам'ять. Різниця швидкостей, ймовірно, на кілька порядків.
Лассе В. Карлсен

10

Тому що операційна система може цього не робити. Операція флеш примушує файлові дані в кеш файлу в оперативній пам'яті, а звідси завдання ОС фактично надсилати їх на диск.


6
Ви маєте рацію, але actuallyтут відносно: якщо цільовий пристрій увімкнено кешування записів, дані, можливо, не досягли фактичних плат / чіпів при os.fsync()поверненні.
Фредерік Хаміді

7

Він промиває внутрішній буфер, який повинен спричинити, що ОС записує буфер у файл. [1] Python використовує буферизацію за замовчуванням в ОС, якщо ви не налаштовуєте це на інше.

Але іноді ОС все ж вирішує не співпрацювати. Особливо з такими чудовими речами, як затримка запису в Windows / NTFS. В основному внутрішній буфер очищений, але буфер ОС все ще тримається за нього. Тож вам доведеться сказати ОС, щоб записати його на диск os.fsync()у тих випадках.

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


0

В основному, flush () очищає ваш буфер оперативної пам’яті, його реальна сила полягає в тому, що він дозволяє продовжувати писати в нього згодом - але це не слід вважати найкращою / найбезпечнішою функцією запису у файл. Це промивання вашої оперативної пам’яті, щоб отримати більше даних, це все. Якщо ви хочете переконатися, що дані надійно записуються у файл, тоді замість цього використовуйте close ().

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.