Почему файл не записывается, пока я не остановлю программу? - PullRequest
23 голосов
/ 22 марта 2012

Я запускаю тест и обнаружил, что файл на самом деле не записывается, пока я не контролирую -C, чтобы прервать программу.Кто-нибудь может объяснить, почему это произошло?

Я ожидал, что он запишется одновременно, поэтому я мог прочитать файл в середине процесса.

import os
from time import sleep

f = open("log.txt", "a+")
i = 0
while True:
  f.write(str(i))
  f.write("\n")
  i += 1
  sleep(0.1)

Ответы [ 7 ]

66 голосов
/ 22 марта 2012

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

Когда вы пишете в файл, вы фактически записываете в «буфер» в памяти.Когда он заполнится, Python автоматически запишет его на диск.Вы можете сказать ему «записать все в буфере на диск сейчас» с помощью

f.flush()

Это не совсем целая история, потому что операционная система, вероятно, также буферизует записи.Вы можете указать it записать буфер файла с помощью

os.fsync(f.fileno())

Наконец, вы можете указать Python не буферизовать определенный файл с помощью open(f, "w", 0) или оставить только 1-строковый буфер с open(f,"w", 1).Естественно, это замедлит все операции с этим файлом, потому что запись идет медленно.

5 голосов
/ 22 марта 2012

Вам нужно f.close(), чтобы очистить буфер записи файла в файл.Или в вашем случае вы можете просто захотеть сделать f.flush(); os.fsync();, чтобы вы могли продолжать цикл с дескриптором открытого файла.

1 голос
/ 22 марта 2012

Вы должны форсировать запись, поэтому я использую следующие строки, чтобы убедиться, что файл записан:

# Two commands together force the OS to store the file buffer to disc
    f.flush()
    os.fsync(f.fileno())
1 голос
/ 22 марта 2012

Вы захотите проверить file.flush() - хотя учтите, что это может не записать данные на диск, чтобы процитировать:

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

Закрытие файла (file.close()) также обеспечит запись данных с использованием with сделает это неявно и, как правило, является лучшим выбором для большей читабельности и ясности, не говоря уже о решении других потенциальных проблем.

0 голосов
/ 22 марта 2012

Файл не записывается, поскольку выходной буфер не очищается до тех пор, пока сбор мусора не вступит в силу, и сбрасывает буфер ввода-вывода (более вероятно, вызывая f.close()).

С другой стороны, в вашем цикле вы можете вызвать f.flush(), а затем os.fsync(), как задокументировано здесь .

f.flush()
os.fsync()

При всем этом, если вы когда-нибудь планируете делиться данными в этом файле с другими частями вашего кода, я настоятельно рекомендую использовать объект StringIO.

0 голосов
/ 22 марта 2012

File Handler для сброса.

f.flush()
0 голосов
/ 22 марта 2012

Это windows-изм. Если вы добавите явный .close(), когда закончите с файлом, он появится в проводнике в то время. Даже простой очистки может быть достаточно (у меня нет окна, пригодного для тестирования). Но в основном f.write на самом деле не пишет , он просто добавляется в буфер записи - пока буфер не будет очищен, вы его не увидите.

В unix файлы обычно отображаются в виде 0-байтового файла в этой ситуации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...