Записать исходный файл Python в файл немедленно

При попытке записать stdout из сценария Python в текстовый файл ( python script.py > log ) текстовый файл создается при запуске команды, но фактический контент не записывается до завершения сценария Python. Например:

script.py:

 import time for i in range(10): print('bla') time.sleep(5) 

печатает в stdout каждые 5 секунд, когда python script.py с python script.py , но когда я вызываю python script.py > log , размер файла журнала остается нулевым до завершения скрипта. Можно ли напрямую записывать в файл журнала, чтобы вы могли следить за ходом выполнения скрипта (например, используя tail )?

3 Solutions collect form web for “Записать исходный файл Python в файл немедленно”

Это происходит потому, что, как правило, когда процесс STDOUT перенаправляется на что-то другое, отличное от терминала, то вывод буферизуется в буфер определенного размера ОС (возможно, 4k или 8k во многих случаях). И наоборот, при выводе на терминал STDOUT будет буферизироваться по строке или вообще не буферизоваться, поэтому вы увидите вывод после каждого \n или для каждого символа.

Обычно вы можете изменить буферизацию STDOUT с stdbuf утилиты stdbuf :

 stdbuf -oL python script.py > log 

Теперь, если вы tail -F log , вы должны увидеть каждый вывод строки сразу же после его создания.


Альтернативно явная промывка выходного потока после каждой печати должна достигать того же. Похоже, sys.stdout.flush() должен достичь этого в Python. Если вы используете Python 3.3 или новее, функция print также имеет ключевое слово flush которое делает это: print('hello', flush=True) .

Это должно сделать работу:

 import time, sys for i in range(10): print('bla') sys.stdout.flush() time.sleep(5) 

Поскольку Python будет буферизовать stdout по умолчанию, здесь я использовал sys.stdout.flush() чтобы очистить буфер.

Другим решением было бы использовать -u (небуферизованный) переключатель python . Итак, следующее:

 python -u script.py >> log 

Вы должны передать flush=True для функции print :

 import time for i in range(10): print('bla', flush=True) time.sleep(5) 

Согласно документации, по умолчанию print не обеспечивает ничего о промывке:

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

И документация для styss sys говорит:

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


Если вы застряли в древней версии python, вам нужно вызвать метод sys.stdout потока sys.stdout :

 import sys import time for i in range(10): print('bla') sys.stdout.flush() time.sleep(5) 
  • Программа, которая может буферизовать stdin или файл
  • Linux: как перенаправить stdout и stderr в logger?
  • Вывод экрана в столбцы, чтобы использовать ширину экрана и избежать прокрутки
  • stdout, stderr и протоколирование с помощью команды script
  • bash: / dev / stderr: разрешение отклонено
  • Как отправить stderr в stdout с помощью трубы в другую команду?
  • Как узнать, перенаправляется ли выход в файл?
  • Возможно ли создать липкое перенаправление из stdout / stderr
  • Как написать скрипт, который может принимать входные данные из stdout
  • Перенаправить bash stdout + stderr в один файл и stderr в другой файл
  • `unbuffer` или` stdbuf` для удаления буферизации stdout?
  • Linux и Unix - лучшая ОС в мире.