Как очистить вывод функции печати?
-
04-07-2019 - |
Вопрос
Как заставить функцию печати Python выводить на экран?
Это не дубликат Отключить буферизацию вывода - связанный вопрос пытается выполнить небуферизованный вывод, хотя это более общий вопрос.Лучшие ответы на этот вопрос слишком содержательны или сложны для этого (они не являются хорошими ответами для этого), и этот вопрос может найти в Google относительный новичок.
Решение
import sys
sys.stdout.flush()
print
по умолчанию печатает на sys.stdout
.
Рекомендации
Питон 2
Питон 3
print()
sys.stdout
- файловый объект — Глоссарий
io.IOBase.flush()
(sys.stdout
наследуетflush
метод изio.IOBase
)
Другие советы
При выполнении python -h
я вижу параметр командной строки :
-u: небуферизованные двоичные stdout и stderr; также PYTHONUNBUFFERED = x см. справочную страницу для получения подробной информации о внутренней буферизации, связанной с '-u'
Вот соответствующий документ .
Начиная с Python 3.3, вы можете принудительно сбросить обычную функцию print()
без использования sys.stdout.flush()
; просто установите " flush " Ключевое слово аргумент истина. Из документации :
print (* objects, 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, и нет аналога для оператора печати). - Вызов
file.flush()
в выходном файле (для этого мы можем обернуть функцию печати Python 2), например:sys.stdout
- примените это к каждому вызову функции печати в модуле с частичной функцией,
print = partial(print, flush=True)
применяется к модулю global. - примените это к процессу с флагом (
-u
) передается команде интерпретатора - примените это к каждому процессу Python в вашей среде с помощью
PYTHONUNBUFFERED=TRUE
(и отключите переменную, чтобы отменить это).
Питон 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()
после печати, например, с помощью оператора печати в 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() и объектах файлов (для строки в sys.stdin), на которую эта опция не влияет.Чтобы обойти эту проблему, вам нужно будет использовать file.readline() внутри while 1:петля.
Изменение настроек по умолчанию для операционной среды оболочки
Вы можете получить такое поведение для всех процессов Python в среде или средах, которые наследуются от среды, если вы установите для переменной среды непустую строку:
например, в Linux или OSX:
$ export PYTHONUNBUFFERED=TRUE
или Windows:
C:\SET PYTHONUNBUFFERED=TRUE
из документы:
PYTHONНЕБУФЕРИРОВАННЫЙ
Если для этого параметра задана непустая строка, это эквивалентно указанию опции -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
работает, но это немного неуклюже. Это означало бы, что программа могла бы вести себя некорректно, если бы пользователь вызывал скрипт без опции stdout
. Я обычно использую пользовательский print
, например:
class flushfile:
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)
... Теперь все ваши sys.stdout
вызовы (которые используют flush
неявно) будут автоматически <=> редактироваться.
Почему бы не попробовать использовать небуферизованный файл?
f = open('xyz.log', 'a', 0)
ИЛИ
sys.stdout = open('out.log', 'a', 0)
Идея Дэна не совсем работает:
#!/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()
В 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)
Я сделал это так в Python 3.4:
'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')