Включена ли буферизация вывода по умолчанию в интерпретаторе Python для sys.stdout
?
Если ответ положительный, какие есть способы его отключения?
Предложения на данный момент:
- Используйте
-u
переключатель командной строки - Заворачивать
sys.stdout
в объект, который очищается после каждой записи - Установить
PYTHONUNBUFFERED
env var sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
Есть ли другой способ установить какой-либо глобальный флаг в sys
/ sys.stdout
программно во время выполнения?
-u
является то, что он не будет работать для скомпилированного байт-кода или для приложений с__main__.py
файлом в качестве точки входа.Ответы:
От Магнуса Лицки ответьте на рассылку :
источник
#!/usr/bin/env python -u
не работает !! смотрите здесь__getattr__
просто чтобы избежать наследства ?!iter()
вместоwhile
цикла:for line in iter(pipe.readline, ''):
. Вам не нужно это на Python 3, гдеfor line in pipe:
дает как можно скорее.Я предпочел бы поставить свой ответ в Как очистить вывод функции печати? или в функции печати Python, которая очищает буфер при вызове? , но так как они были помечены как дубликаты этого (что я не согласен), я отвечу здесь.
Начиная с Python 3.3, print () поддерживает ключевое слово аргумент "flush" ( см. Документацию ):
источник
Кредиты: «Себастьян», где-то в списке рассылки Python.
источник
flush=True
параметр вprint()
функцию начиная с Python 3.3.os.fdopen(sys.stdout.fileno(), 'wb', 0)
(обратите вниманиеb
на двоичный файл) иflush=True
работа для меня в 3.6.4. Однако, если вы используете подпроцесс для запуска другого скрипта, убедитесь, что вы указалиpython3
, если у вас установлено несколько экземпляров python.os.fdopen(sys.stdout.fileno(), 'wb', 0)
вы получите двоичный объект файла, а неTextIO
поток. Вы должны будете добавитьTextIOWrapper
к миксу (убедитесь, что вы включили,write_through
чтобы исключить все буферы, или используйтеline_buffering=True
для сброса только на новых строках).Да, это так.
Вы можете отключить его в командной строке с помощью ключа "-u".
В качестве альтернативы, вы можете вызывать .flush () для sys.stdout при каждой записи (или заключать его в объект, который делает это автоматически)
источник
Это относится к ответу Кристована Д. Соузы, но я пока не могу комментировать.
Прямой вперед способ использования
flush
ключевого слова аргумента Python 3 для того , чтобы всегда иметь небуферизованный выход есть:после этого print всегда будет сбрасывать вывод напрямую (за исключением
flush=False
заданного).Обратите внимание, (а) что это отвечает на вопрос только частично, так как не перенаправляет весь вывод. Но я думаю,
print
что это наиболее распространенный способ создания вывода вstdout
/stderr
в Python, поэтому эти 2 строки охватывают, вероятно, большинство случаев использования.Обратите внимание (б), что он работает только в модуле / скрипте, где вы его определили. Это может быть хорошо при написании модуля, так как он не связывается с
sys.stdout
.Python 2 не предоставляет
flush
аргумент, но вы можете эмулировать функцию Python 3-type,print
как описано здесь https://stackoverflow.com/a/27991478/3734258 .источник
flush
в python2 kwarg.Без сохранения старого sys.stdout disable_stdout_buffering () не идемпотентен, и множественные вызовы приведут к ошибке, подобной этой:
Другая возможность:
(Присоединение к gc.garbage не очень хорошая идея, потому что это место, где помещаются несвободные циклы, и вы можете проверить их.)
источник
stdout
все еще живет,sys.__stdout__
как некоторые предполагали, мусор не понадобится, верно? Это крутой трюк, хотя.ValueError: can't have unbuffered text I/O
при вызове возникнет исключениеprint()
.Следующие работы в Python 2.6, 2.7 и 3.2:
источник
OSError: [Errno 29] Illegal seek
для строкиsys.stdout = os.fdopen(sys.stdout.fileno(), 'a+', buf_arg)
Да, он включен по умолчанию. Вы можете отключить его, используя опцию -u в командной строке при вызове python.
источник
Вы также можете запустить Python с помощью утилиты stdbuf :
stdbuf -oL python <script>
источник
-oL
включении) по-прежнему буферизируется - см. F / e stackoverflow.com/questions/58416853/… , спрашивающий, почемуend=''
вывод больше не отображается немедленно.print(..., end='', flush=True)
указать, где это имеет значение? OTOH, когда несколько программ записывают в один и тот же выход одновременно, компромисс имеет тенденцию переходить от непосредственного прогресса к уменьшению путаницы вывода, и буферизация строки становится привлекательной. Так что, может быть , это лучше не писать явноflush
и управление буферизацией внешне?flush
. Внешнее управление буферизацией здесь является обязательным обходнымВ Python 3 вы можете «обезьянько-патчить» функцию печати, чтобы всегда отправлять flush = True:
Как указано в комментарии, вы можете упростить это, привязав параметр flush к значению через
functools.partial
:источник
functools.partial
?print = functools.partial(print, flush=True)
у меня отлично работаетimport builtins; builtins.print = partial(print, flush=True)
Вы также можете использовать fcntl для изменения файловых флагов на лету.
источник
Можно переопределить только
write
метод,sys.stdout
который вызываетflush
. Предлагаемый способ реализации приведен ниже.Значение
w
аргумента по умолчанию будет сохранять исходнуюwrite
ссылку на метод. Послеwrite_flush
определения оригиналwrite
может быть переопределен.Код предполагает, что
stdout
импортируется таким образомfrom sys import stdout
.источник
Вы можете создать небуферизованный файл и назначить этот файл для sys.stdout.
Вы не можете волшебным образом изменить системный стандартный вывод; так как он поставляется вашей программой на Python операционной системой.
источник
Вариант, который работает без сбоев (по крайней мере, на win32; python 2.7, ipython 0.12), затем вызывается впоследствии (несколько раз):
источник
sys.stdout is sys.__stdout__
вместо того, чтобы полагаться на объект замены, имеющий атрибут имени?(Я разместил комментарий, но он как-то потерялся. Итак, снова :)
Как я заметил, CPython (по крайней мере, в Linux) ведет себя по-разному в зависимости от того, куда выводятся данные. Если он переходит к tty, то вывод сбрасывается после каждого '
\n'
Если он идет в канал / процесс, тогда он буферизуется, и вы можете использовать
flush()
основанные решения или опцию -u, рекомендованную выше.Немного связано с буферизацией вывода:
если вы перебираете строки на входе с
for line in sys.stdin:
...
затем реализация for в CPython будет некоторое время собирать входные данные, а затем выполнять тело цикла для набора входных строк. Если ваш сценарий собирается записать вывод для каждой строки ввода, это может выглядеть как буферизация вывода, но на самом деле это пакетная обработка, и поэтому ни один из
flush()
методов и т. Д. Не поможет. Интересно, что у вас нет такого поведения в Pypy . Чтобы избежать этого, вы можете использоватьwhile True: line=sys.stdin.readline()
...
источник
for line in sys.stdin
противfor line in iter(sys.stdin.readline, "")
for line in sys.stdin
предоставляет отложенный ответ)Один из способов получить небуферизованный вывод - использовать
sys.stderr
вместоsys.stdout
или просто вызватьsys.stdout.flush()
чтобы явно вызвать запись.Вы можете легко перенаправить все напечатанное, выполнив:
Или перенаправить только для конкретного
print
заявления:Чтобы сбросить стандартный вывод, вы можете просто сделать:
источник