Что именно делает Python file.flush ()?

137

Я нашел это в документации по Python для файловых объектов :

flush () не обязательно записывает данные файла на диск. Используйте flush (), а затем os.fsync (), чтобы убедиться в этом.

Итак, мой вопрос: что именно flushделает Python ? Я думал, что это заставляет записывать данные на диск, но теперь я вижу, что это не так. Зачем?

фанат
источник

Ответы:

220

Обычно используется два уровня буферизации:

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

Внутренние буферы - это буферы, создаваемые средой выполнения / библиотекой / языком, для которых вы программируете, и призваны ускорить процесс, избегая системных вызовов для каждой записи. Вместо этого, когда вы записываете в файловый объект, вы записываете в его буфер, и всякий раз, когда буфер заполняется, данные записываются в реальный файл с использованием системных вызовов.

Однако из-за буферов операционной системы это может не означать, что данные записываются на диск . Это может означать, что данные копируются из буферов, поддерживаемых вашей средой выполнения, в буферы, поддерживаемые операционной системой.

Если вы что-то пишете, и это попадает в буфер (только), и питание отключается на вашем компьютере, эти данные не находятся на диске, когда машина выключается.

Итак, для того , чтобы помочь с этим у вас есть flushи fsyncметоды, на соответствующих объектах.

Первое, flushпросто записывает любые данные, которые остаются в программном буфере, в фактический файл. Обычно это означает, что данные будут скопированы из буфера программы в буфер операционной системы.

В частности, это означает, что если другой процесс имеет тот же файл, открытый для чтения, он сможет получить доступ к данным, которые вы только что сбросили в файл. Однако это не обязательно означает, что он «постоянно» хранится на диске.

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

Как правило, вам не нужно беспокоиться о любом из этих методов, но если вы находитесь в ситуации, когда паранойя о том, что на самом деле заканчивается на диске, является хорошей вещью, вы должны сделать оба вызова в соответствии с инструкциями.


Приложение в 2018 году.

Обратите внимание, что диски с механизмами кеширования стали гораздо более распространенными, чем в 2013 году, поэтому теперь задействовано еще больше уровней кэширования и буферов. Я предполагаю, что эти буферы также будут обрабатываться вызовами sync / flush, но я действительно не знаю.

Лассе В. Карлсен
источник
10
Когда я использую with file('blah') as fd: #dostuffконструкцию, я знаю, что она гарантирует закрытие файлового дескриптора. Это также сбрасывает или синхронизирует?
Марцин
3
@ Марчин: он мигает, но не синхронизируется.
Алекс я
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 ().

мкА.
источник