Как сбросить вывод функции печати?

Как заставить функцию печати Python выводить на экран?

This is not a duplicate of Disable output buffering - the linked question is attempting unbuffered output, while this is more general. The top answers in that question are too powerful or involved for this one (they're not good answers for this), and this question can be found on Google by a relative newbie.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1 352
0
896 375
13
Перейти к ответу Данный вопрос помечен как решенный

Ответы 13

Ответ принят как подходящий

В Python 3 print может принимать необязательный аргумент flush

print("Hello world!", flush=True)

На Python 2 вам нужно будет сделать

import sys
sys.stdout.flush()

после звонка print. По умолчанию print печатает в sys.stdout (дополнительные сведения о файловые объекты см. В документации).

Запустив python -h, я вижу параметр командной строки:

-u : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x see man page for details on internal buffering relating to '-u'

Вот соответствующий документ.

Если вы используете его на платформе Linux / Unix, вы можете добавить -u в командную строку интерпретатора (первая строка файла сценария), поэтому измените первую строку с (что-то вроде) #!/usr/bin/python3 на #!/usr/bin/python3 -u - теперь, когда вы запустите свой скрипт (например, ./my_script.py) -u всегда будет добавлен за вас

James Stevens 07.09.2020 20:22

Использование переключателя командной строки -u работает, но немного неуклюже. Это означало бы, что программа потенциально могла бы вести себя некорректно, если бы пользователь запускал скрипт без опции -u. Обычно я использую кастомный stdout, например:

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)

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

Я рекомендую не наследовать от файла, а затем делегировать его на стандартный вывод, добавляя. def __getattr__(self,name): return object.__getattribute__(self.f, name)

diedthreetimes 23.06.2013 23:21

Без изменений, предложенных комментарием @diedthreetimes, я получаю «ValueError: операция ввода-вывода в закрытом файле»

blueFast 28.04.2015 01:43

Идея Дэна не совсем работает:

#!/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 and stderr needn’t be built-in file objects: any object is acceptable as long as it has a write() method that takes a string argument.

так меняется

class flushfile(file):

к

class flushfile(object):

заставляет его работать нормально.

Нет голоса, потому что это решение IS @ Dan ... (вам лучше прокомментировать сообщение Дэна, а не копировать его решение)

gecco 15.01.2013 19:30

Почему бы не попробовать использовать небуферизованный файл?

f = open('xyz.log', 'a', 0)

ИЛИ ЖЕ

sys.stdout = open('out.log', 'a', 0)

Он не хочет создавать небуферизованный файл; он хочет сделать существующий стандартный вывод (перенаправленный на консоль, терминал или что-то еще: это не должно быть изменено) небуферизованным.

blueFast 28.04.2015 15:58

Вот моя версия, в которой также есть 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.4.0. С другими версиями, производными от file, я получаю сообщение об ошибке. Класса file нет.

Colin D Bennett 23.09.2014 00:58

Также, как предлагается в этот блог, можно повторно открыть sys.stdout в небуферизованном режиме:

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

После этого каждая операция stdout.write и print будет автоматически сбрасываться.

В Ubuntu 12.04 в python 2.7 это дает мне UnsupportedOperation: IOStream has no fileno.

drevicko 01.07.2015 07:58

Упс, Python 3 обнаружил. Это не позволит мне выполнить этот фрагмент кода!

EKons 30.04.2016 20:43

Меня смущает эта идиома. После того, как вы это сделаете, разве не осталось двух объектов типа File (исходный sys.stdout и новый sys.stdout), которые оба думают, что они «владеют» файлом? Это плохо, правда?

Don Hatch 19.10.2018 16:41

Начиная с Python 3.3, вы можете принудительно сбросить обычную функцию print() без использования sys.stdout.flush(); просто установите для аргумента ключевого слова "flush" значение true. От документация:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

Print objects to the stream file, separated by sep and followed by end. sep, end and file, if present, must be given as keyword arguments.

All non-keyword arguments are converted to strings like str() does and written to the stream, separated by sep and followed by end. Both sep and end must be strings; they can also be None, which means to use the default values. If no objects are given, print() will just write end.

The file argument must be an object with a write(string) method; if it is not present or None, sys.stdout will be used. Whether output is buffered is usually determined by file, but if the flush keyword argument is true, the stream is forcibly flushed.

Я сделал это так в Python 3.4:

'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end = "")
message('I am flushing out now...')

В Python 3.x функция print() была расширена:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

Итак, вы можете просто сделать:

print("Visiting toilet", flush=True)

Запись в Python Docs

How to flush output of Python print?

Я предлагаю пять способов сделать это:

  • В Python 3 вызовите print(..., flush=True) (аргумент flush недоступен в функции печати Python 2, и нет аналога для оператора печати).
  • Вызовите file.flush() в выходном файле (для этого мы можем обернуть функцию печати Python 2), например sys.stdout
  • примените это к каждому вызову функции печати в модуле с частичной функцией
    print = partial(print, flush=True) применяется к модулю global.
  • примените это к процессу с флагом (-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() после печати, например, с помощью оператора печати в 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

Из документы:

Force stdin, stdout and stderr to be totally unbuffered. On systems where it matters, also put stdin, stdout and stderr in binary mode.

Note that there is internal buffering in file.readlines() and File Objects (for line in sys.stdin) which is not influenced by this option. To work around this, you will want to use file.readline() inside a while 1: loop.

Изменение значения по умолчанию для операционной среды оболочки

Вы можете получить такое поведение для всех процессов python в среде или средах, которые наследуются от среды, если вы установите для переменной среды непустую строку:

например, в Linux или OSX:

$ export PYTHONUNBUFFERED=TRUE

или Windows:

C:\SET PYTHONUNBUFFERED=TRUE

из документы:

PYTHONUNBUFFERED

If this is set to a non-empty string it is equivalent to specifying the -u option.


Дополнение

Вот справка по функции печати из 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.

Для любопытных, переходящих с более ранних версий Python: версия __future__ не включает flush, потому что «аргумент flush был добавлен в Python 3.3 (после того, как print () был перенесен в 2.7 через будущий импорт)» bugs.python.org/issue28458

Oliver 18.03.2020 04:46

Это должен быть принятый ответ. Предоставляет обходные пути и много информации.

TheTechRobo36414519 25.01.2021 01:16

В 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)

этот ответ кажется немного легким с учетом всех остальных качественных ответов. вы можете добавить к нему немного больше.

Semicolons and Duct Tape 15.05.2016 22:18

Сначала я изо всех сил пытался понять, как работает опция промывки. Я хотел сделать «отображение загрузки», и вот решение, которое я нашел:

for i in range(100000):
    print('{:s}\r'.format(''), end='', flush=True)
    print('Loading index: {:d}/100000'.format(i+1), end='')

Первая строка сбрасывает предыдущий отпечаток, а вторая строка - новое обновленное сообщение. Я не знаю, существует ли здесь однострочный синтаксис.

Другие вопросы по теме