Как очистить вывод функции печати?
Как заставить функцию печати Python выводить на экран?
Это не дубликат буферизации вывода данных - связанный вопрос пытается получить небуферизованный вывод, хотя это более общий вопрос. Лучшие ответы на этот вопрос слишком сильны или вовлечены для этого (они не являются хорошими ответами для этого), и этот вопрос может быть найден в Google относительным новичком.
14 ответов
import sys
sys.stdout.flush()
Печать по умолчанию печатает на sys.stdout
,
Рекомендации:
Бег python -h
Я вижу параметр командной строки:
-u: небуферизованный двоичный stdout и stderr; также PYTHONUNBUFFERED=x см. справочную страницу для деталей о внутренней буферизации, связанной с '-u'
Начиная с Python 3.3, вы можете заставить нормальный print()
функция промывки без использования sys.stdout.flush()
; просто установите для аргумента ключевого слова flush значение true. Из документации:
print (* объекты, sep=' ', end='\n', file=sys.stdout, flush=False)
Печатайте объекты в файл потока, разделяя их sep и заканчивая end. sep, end и file, если они есть, должны быть заданы в качестве аргументов ключевых слов.
Все аргументы, не являющиеся ключевыми словами, преобразуются в строки, как это делает str(), и записываются в поток, разделяются sep и сопровождаются end. И sep, и end должны быть строками; они также могут быть None, что означает использование значений по умолчанию. Если объекты не указаны, print() просто напишет end.
Аргумент файла должен быть объектом с методом write(string); если он отсутствует или отсутствует, будет использоваться sys.stdout. Будь буферизован вывод, обычно определяется файлом, но если аргумент ключевого слова flush равен true, поток принудительно сбрасывается.
Как очистить вывод печати Python?
Я предлагаю пять способов сделать это:
- В Python 3 звоните
print(..., flush=True)
(аргумент flush недоступен в функции печати Python 2, и аналога для оператора print нет). - Вызов
file.flush()
в выходном файле (мы можем обернуть функцию печати Python 2, чтобы сделать это), например,sys.stdout
- применить это к каждому вызову функции печати в модуле с частичной функцией,
print = partial(print, flush=True)
применяется к модулю глобальный. - применить это к процессу с флагом (
-u
) передал переводчику команду - применить это к каждому процессу Python в вашей среде с
PYTHONUNBUFFERED=TRUE
(и отмените переменную, чтобы отменить это).
Python 3.3+
Используя Python 3.3 или выше, вы можете просто предоставить flush=True
в качестве ключевого аргумента print
функция:
print('foo', flush=True)
Python 2 (или < 3.3)
Они не сделали бэкпорт flush
Аргумент к Python 2.7 Итак, если вы используете Python 2 (или меньше 3.3) и хотите получить код, совместимый как с 2, так и с 3, могу ли я предложить следующий код совместимости. (Обратите внимание __future__
импорт должен быть в / очень "в верхней части вашего модуля "):
from __future__ import print_function
import sys
if sys.version_info[:2] < (3, 3):
old_print = print
def print(*args, **kwargs):
flush = kwargs.pop('flush', False)
old_print(*args, **kwargs)
if flush:
file = kwargs.get('file', sys.stdout)
# Why might file=None? IDK, but it works for print(i, file=None)
file.flush() if file is not None else sys.stdout.flush()
Приведенный выше код совместимости будет охватывать большинство применений, но для более тщательного рассмотрения см. six
модуль.
Кроме того, вы можете просто позвонить file.flush()
после печати, например, с помощью оператора print в Python 2:
import sys
print 'delayed output'
sys.stdout.flush()
Изменение значения по умолчанию в одном модуле на flush=True
Вы можете изменить значение по умолчанию для функции печати, используя functools.partial в глобальной области видимости модуля:
import functools
print = functools.partial(print, flush=True)
если вы посмотрите на нашу новую частичную функцию, по крайней мере, в Python 3:
>>> print = functools.partial(print, flush=True)
>>> print
functools.partial(<built-in function print>, flush=True)
Мы видим, что это работает как обычно:
>>> print('foo')
foo
И мы можем переопределить новое значение по умолчанию:
>>> print('foo', flush=False)
foo
Обратите внимание, это только изменяет текущую глобальную область, потому что имя печати в текущей глобальной области будет перекрывать встроенную print
функция (или разыменование функции совместимости, если используется Python 2, в этой текущей глобальной области видимости).
Если вы хотите сделать это внутри функции, а не в глобальной области видимости модуля, вы должны дать ему другое имя, например:
def foo():
printf = functools.partial(print, flush=True)
printf('print stuff like this')
Если вы объявляете его глобальным в функции, вы изменяете его в глобальном пространстве имен модуля, поэтому вы должны просто поместить его в глобальное пространство имен, если только это конкретное поведение не является именно тем, что вам нужно.
Изменение значения по умолчанию для процесса
Я думаю, что лучшим вариантом здесь является использование -u
флаг для получения небуферизованного вывода.
$ python -u script.py
или же
$ python -um package.module
Из документов:
Заставьте stdin, stdout и stderr быть полностью небуферизованными. В системах, где это имеет значение, также установите stdin, stdout и stderr в двоичном режиме.
Обратите внимание, что в file.readlines() и File Objects (для строки в sys.stdin) есть внутренняя буферизация, на которую не влияет эта опция. Чтобы обойти это, вы захотите использовать file.readline() внутри цикла while 1:.
Изменение значения по умолчанию для операционной среды оболочки
Вы можете получить это поведение для всех процессов Python в среде или средах, которые наследуются от среды, если для переменной среды задать непустую строку:
например, в Linux или OSX:
$ export PYTHONUNBUFFERED=TRUE
или Windows:
C:\SET PYTHONUNBUFFERED=TRUE
из документов:
PYTHONUNBUFFERED
Если для этого параметра задана непустая строка, это эквивалентно указанию опции -u.
добавление
Вот справка по функции печати из Python 2.7.12 - обратите внимание, что нет flush
аргумент:
>>> from __future__ import print_function
>>> help(print)
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
Также, как предлагается в этом блоге, можно снова открыть sys.stdout
в небуферизованном режиме:
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
каждый stdout.write
а также print
операция будет автоматически сброшена позже.
С Python 3.x они расширили print()
функция:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Итак, вы можете просто сделать:
print("Visiting toilet", flush=True)
С использованием -u
переключатель командной строки работает, но он немного неуклюжий. Это означало бы, что программа могла бы вести себя неправильно, если бы пользователь вызывал скрипт без -u
вариант. Я обычно использую обычай stdout
, как это:
class flushfile(object):
def __init__(self, f):
self.f = f
def write(self, x):
self.f.write(x)
self.f.flush()
import sys
sys.stdout = flushfile(sys.stdout)
... теперь все твои print
звонки (которые используют sys.stdout
неявно), будет автоматически flush
редактор
Почему бы не попробовать использовать небуферизованный файл?
f = open('xyz.log', 'a', 0)
ИЛИ ЖЕ
sys.stdout = open('out.log', 'a', 0)
В Python 3 вы можете перезаписать функцию печати со значением по умолчанию flush = True
def print(*objects, sep=' ', end='\n', file=sys.stdout, flush=True):
__builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)
Идея Дэна не совсем работает:
#!/usr/bin/env python
class flushfile(file):
def __init__(self, f):
self.f = f
def write(self, x):
self.f.write(x)
self.f.flush()
import sys
sys.stdout = flushfile(sys.stdout)
print "foo"
Результат:
Traceback (most recent call last):
File "./passpersist.py", line 12, in <module>
print "foo"
ValueError: I/O operation on closed file
Я считаю, что проблема в том, что он наследуется от класса файлов, что на самом деле не нужно. Согласно документам для sys.stdout:
stdout и stderr не обязательно должны быть встроенными файловыми объектами: любой объект приемлем, если у него есть метод write(), который принимает строковый аргумент.
так меняется
class flushfile(file):
в
class flushfile(object):
делает это работает просто отлично.
Вот моя версия, которая также предоставляет writelines() и fileno():
class FlushFile(object):
def __init__(self, fd):
self.fd = fd
def write(self, x):
ret = self.fd.write(x)
self.fd.flush()
return ret
def writelines(self, lines):
ret = self.writelines(lines)
self.fd.flush()
return ret
def flush(self):
return self.fd.flush
def close(self):
return self.fd.close()
def fileno(self):
return self.fd.fileno()
import sys
print 'This will be output immediately.'
sys.stdout.flush()
Я сделал это так в Python 3.4:
'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')
Сначала я изо всех сил пытался понять, как работает опция промывки. Я хотел сделать "отображение загрузки", и вот решение, которое я нашел:
for i in range(100000):
print('{:s}\r'.format(''), end='', flush=True)
print('Loading index: {:d}/100000'.format(i+1), end='')
Первая строка сбрасывает предыдущий отпечаток, а вторая строка - новое обновленное сообщение. Я не знаю, существует ли здесь однострочный синтаксис.
Любимое решение Дэна! Для python3 сделайте:
import io,sys
class flushfile:
def __init__(self, f):
self.f = f
def write(self, x):
self.f.write(x)
self.f.flush()
sys.stdout = flushfile(sys.stdout)