Как часто Python сбрасывается в файл?

228
  1. Как часто Python сбрасывает в файл?
  2. Как часто Python сбрасывается на стандартный вывод?

Я не уверен насчет (1).

Что касается (2), я считаю, что Python сбрасывает на стандартный вывод после каждой новой строки. Но если вы перегружаете стандартный вывод в файл, он очищается так часто?

Тим МакДжилтон
источник

Ответы:

332

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

Например, функция open принимает аргумент размера буфера.

http://docs.python.org/library/functions.html#open

Msgstr "Необязательный аргумент буферизации указывает желаемый размер буфера файла:"

  • 0 означает небуферизованный,
  • 1 означает строку в буфере,
  • любое другое положительное значение означает использование буфера (приблизительно) этого размера.
  • Отрицательная буферизация означает использование системной настройки по умолчанию, которая обычно буферизуется строкой для tty-устройств и полностью буферизуется для других файлов.
  • Если опущено, используется системное значение по умолчанию.

код:

bufsize = 0
f = open('file.txt', 'w', buffering=bufsize)
Кори Голдберг
источник
23
+1 за часть с "буферизацией строки". Это именно то, что я искал, и это работает как шарм.
Обуздать
2
Используя Python 3.4.3, open('file.txt', 'w', 1)я получаю правильную буферизацию строки. Но если я сделаю что-то большее (я хотел open('file.txt', 'w', 512)), то он полностью io.DEFAULT_BUFFER_SIZEзаполнит 8192. Это ошибка Python, ошибка Linux или ошибка ID10t?
Бруно Броноски
Можно ли изменить буферизацию для уже открытых потоков? Скажем, я хочу stdoutиспользовать линейную буферизацию независимо от того, является ли она консолью или перенаправлена ​​в файл?
Михаил Т.
1
@CharlieParker, когда вы вызываете write()дескриптор файла, выходные данные буферизуются в памяти и накапливаются до тех пор, пока буфер не заполнится ... в этот момент буфер "очищается" (содержимое записывается из буфера в файл). Вы можете явно очистить буфер, вызвав flush()метод для дескриптора файла.
Кори Голдберг
3
Обратите внимание, что функция unbuffered (0) доступна только в двоичном режиме, а строка с буферизацией (1) доступна только в текстовом режиме.
ЗайдХ
173

Вы также можете принудительно сбросить буфер в файл программным flush()способом.

with open('out.log', 'w+') as f:
    f.write('output is ')
    # some work
    s = 'OK.'
    f.write(s)
    f.write('\n')
    f.flush()
    # some other work
    f.write('done\n')
    f.flush()

Я нашел это полезным, когда хвостовой файл с tail -f.

Кортина
источник
54
Из документов:Note: flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
bobismijnnaam
1
@bobismijnnaam в следующий раз ссылка на указанные документы. Единственная ссылка, которую я могу найти, - это github.com/jprzywoski/python-reference/blob/master/source/docs/… и я не знаю, кто это.
Бруно Броноски
5
@ Бруно Броноски Хороший вопрос. Документы: Note: flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
bobismijnnaam
то, что я смущен, - то, что термин flushingдаже означает. Зачем нам это нужно? Для чего это? почему я должен заботиться об этом?
Чарли Паркер
@CharlieParker, когда вы пишете, вы записываете копию (часть) файла в ОЗУ, который некоторое время может не сохраняться на диск. Это повышает производительность, но может означать потерю данных, если эта копия никогда не будет записана (диск извлечен, сбой ОС и т. Д.). flush () говорит Python немедленно записать этот буфер обратно на диск. (Затем os.fsync () говорит операционной системе также делать это. Есть много слоев буферов ...)
Рена
13

Я не знаю, относится ли это и к Python, но я думаю, что это зависит от операционной системы, которую вы используете.

Например, в Linux вывод в терминал сбрасывает буфер на новую строку, тогда как при выводе в файлы он сбрасывается только при заполнении буфера (по умолчанию). Это потому, что более эффективно очищать буфер меньше раз, и пользователь с меньшей вероятностью заметит, если вывод не сбрасывается на новую строку в файле.

Возможно, вы сможете автоматически очистить вывод, если это то, что вам нужно.

РЕДАКТИРОВАТЬ: Я думаю, что вы бы автоматически сбросить в Python таким образом (на основе здесь )

#0 means there is no buffer, so all output
#will be auto-flushed
fsock = open('out.log', 'w', 0)
sys.stdout = fsock
#do whatever
fsock.close()
KLee1
источник
12

Вы также можете проверить размер буфера по умолчанию, вызвав атрибут DEFAULT_BUFFER_SIZE только для чтения из модуля io.

import io
print (io.DEFAULT_BUFFER_SIZE)
N Randhawa
источник
1
Спасибо! Приятно знать, что python устанавливает его так, как определяет ОС ... но это помогает узнать, что предопределено ОС.
Cometsong
2

Вот другой подход, вплоть до ОП, чтобы выбрать, какой он предпочитает.

При включении приведенного ниже кода в __init__файл .py перед любым другим кодом сообщения, напечатанные с printошибками, и любые ошибки больше не будут записываться в файл Ableton Log.txt, а для разделения файлов на вашем диске:

import sys

path = "/Users/#username#"

errorLog = open(path + "/stderr.txt", "w", 1)
errorLog.write("---Starting Error Log---\n")
sys.stderr = errorLog
stdoutLog = open(path + "/stdout.txt", "w", 1)
stdoutLog.write("---Starting Standard Out Log---\n")
sys.stdout = stdoutLog

(для Mac изменить #username# имя вашей пользовательской папки. В Windows путь к вашей пользовательской папке будет иметь другой формат)

Когда вы открываете файлы в текстовом редакторе, который обновляет его содержимое при изменении файла на диске (например, для Mac: TextEdit не делает, а TextWrangler делает), вы увидите, что журналы обновляются в режиме реального времени.

Авторы: этот код был скопирован в основном из сценариев панели управления liveAPI Натаном Рамеллой

Mattijs
источник