Pertanyaan Bagaimana cara mem-flush output dari fungsi print?


Bagaimana cara memaksa fungsi cetak Python untuk keluar ke layar?

Ini bukan duplikat dari Nonaktifkan penyangga keluaran - pertanyaan yang terkait adalah mencoba keluaran yang tidak disumbangkan, sementara ini lebih umum. Jawaban teratas dalam pertanyaan itu terlalu kuat atau terlibat untuk pertanyaan ini (mereka bukan jawaban yang bagus untuk ini), dan pertanyaan ini dapat ditemukan di Google oleh seorang pemula yang relatif.


886
2017-10-23 17:59


asal


Jawaban:


import sys
sys.stdout.flush()

Cetak secara default mencetak ke sys.stdout.

Referensi:


1049
2017-10-23 18:04



Lari python -h, Saya melihat a opsi baris perintah:

-u: stdout biner dan stderr unbuffered; juga PYTHONUNBUFFERED = x            lihat halaman manual untuk detail tentang penyangga internal yang berkaitan dengan '-u'

Ini dia dokumen yang relevan.


292
2017-10-23 18:06



Sejak Python 3.3, Anda dapat memaksa normal print() berfungsi untuk menyiram tanpa perlu digunakan sys.stdout.flush(); cukup atur argumen kata kunci "flush" ke true. Dari dokumentasi:

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

Mencetak objek ke file aliran, dipisahkan dengan sep dan diikuti oleh akhir. sep, akhir dan file, jika ada, harus diberikan sebagai argumen kata kunci.

Semua argumen non-kata kunci diubah menjadi string seperti str () dilakukan dan ditulis ke aliran, dipisahkan oleh sep dan diikuti oleh akhir. Baik sep dan ujungnya harus string; mereka juga bisa Tidak ada, yang berarti menggunakan nilai default. Jika tidak ada objek yang diberikan, cetak () hanya akan menulis akhir.

Argumen file harus berupa objek dengan metode penulisan (string); jika tidak ada atau Tidak ada, sys.stdout akan digunakan. Apakah output buffered biasanya ditentukan oleh file, tetapi jika argumen kata kunci flush benar, aliran secara paksa memerah.


244
2018-04-17 20:10



Bagaimana cara mem-flush output dari Python print?

Saya menyarankan lima cara untuk melakukan ini:

  • Di Python 3, telepon print(..., flush=True) (argumen flush tidak tersedia dalam fungsi cetak Python 2, dan tidak ada analog untuk pernyataan cetak).
  • Panggilan file.flush() pada file output (kita dapat membungkus fungsi cetak python 2 untuk melakukan ini), misalnya, sys.stdout
  • menerapkan ini untuk setiap fungsi cetak panggilan dalam modul dengan fungsi parsial,
    print = partial(print, flush=True) diterapkan ke modul global.
  • menerapkan ini ke proses dengan bendera (-u) diteruskan ke perintah interpreter
  • berlaku ini untuk setiap proses python di lingkungan Anda dengan PYTHONUNBUFFERED=TRUE (dan unset variabel untuk membatalkan ini).

Python 3.3+

Dengan menggunakan Python 3.3 atau lebih tinggi, Anda cukup memberikannya flush=True sebagai argumen kata kunci untuk print fungsi:

print('foo', flush=True) 

Python 2 (atau <3.3)

Mereka tidak mendukung flush argumen ke Python 2.7 Jadi jika Anda menggunakan Python 2 (atau kurang dari 3.3), dan ingin kode yang kompatibel dengan kedua 2 dan 3, saya sarankan kode kompatibilitas berikut. (Perhatikan __future__impor harus pada / sangat "dekat atas modul Anda"):

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

Kode kompatibilitas di atas akan mencakup sebagian besar penggunaan, tetapi untuk perawatan yang jauh lebih menyeluruh, lihat six modul.

Atau, Anda cukup menelepon file.flush() setelah mencetak, misalnya, dengan pernyataan cetak dengan Python 2:

import sys
print 'delayed output'
sys.stdout.flush()

Mengubah default dalam satu modul menjadi flush=True

Anda dapat mengubah default untuk fungsi cetak dengan menggunakan functools.partial pada lingkup global modul:

import functools
print = functools.partial(print, flush=True)

jika Anda melihat fungsi parsial baru kami, setidaknya dengan Python 3:

>>> print = functools.partial(print, flush=True)
>>> print
functools.partial(<built-in function print>, flush=True)

Kita bisa melihatnya bekerja seperti biasa:

>>> print('foo')
foo

Dan kita benar-benar dapat mengganti default baru:

>>> print('foo', flush=False)
foo

Catatan lagi, ini hanya mengubah lingkup global saat ini, karena nama cetak pada lingkup global saat ini akan membayangi builtin print function (atau dereference fungsi kompatibilitas, jika menggunakan Python 2, dalam lingkup global saat ini).

Jika Anda ingin melakukan ini di dalam fungsi, bukan pada lingkup global modul, Anda harus memberinya nama yang berbeda, misalnya:

def foo():
    printf = functools.partial(print, flush=True)
    printf('print stuff like this')

Jika Anda menyatakannya global dalam suatu fungsi, Anda mengubahnya pada namespace global modul, jadi Anda harus meletakkannya di ruang nama global, kecuali perilaku khusus itu persis seperti yang Anda inginkan.

Mengubah default untuk proses

Saya pikir pilihan terbaik di sini adalah menggunakan -u bendera untuk mendapatkan output yang tidak disangga.

$ python -u script.py

atau

$ python -um package.module

Dari dokumen:

Memaksa stdin, stdout dan stderr menjadi sama sekali tidak di-budi. Pada sistem yang penting, masukkan stdin, stdout dan stderr dalam mode biner.

Perhatikan bahwa ada buffer internal di file.readlines () dan File Objects (untuk baris dalam sys.stdin) yang tidak dipengaruhi oleh opsi ini. Untuk mengatasi ini, Anda akan ingin menggunakan file.readline () di dalam while 1: loop.

Mengubah default untuk lingkungan operasi shell

Anda bisa mendapatkan perilaku ini untuk semua proses python di lingkungan atau lingkungan yang mewarisi dari lingkungan jika Anda mengatur variabel lingkungan ke string nonempty:

misalnya, di Linux atau OSX:

$ export PYTHONUNBUFFERED=TRUE

atau Windows:

C:\SET PYTHONUNBUFFERED=TRUE

dari dokumen:

PYTHONUNBUFFERED

Jika ini disetel ke string yang tidak kosong, ini setara dengan menentukan opsi -u.


Tambahan

Inilah bantuan pada fungsi cetak dari Python 2.7.12 - perhatikan bahwa ada tidak  flush argumen:

>>> 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.

100
2018-02-17 21:01



Juga seperti yang disarankan di blog ini seseorang dapat membuka kembali sys.stdout dalam mode unbuffered:

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

Setiap stdout.write dan print operasi akan secara otomatis memerah sesudahnya.


65
2018-02-27 08:38



Menggunakan -u saklar baris perintah bekerja, tetapi sedikit kikuk. Itu berarti bahwa program akan berpotensi berperilaku salah jika pengguna meminta skrip tanpa -u pilihan. Saya biasanya menggunakan kebiasaan stdout, seperti ini:

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)

... Sekarang semua milikmu print panggilan (yang digunakan sys.stdout secara implisit), akan secara otomatis flushed.


30
2017-10-23 19:54



Dengan Python 3.x mereka memperluas print()fungsi:

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

Jadi, Anda bisa melakukannya:

print("Visiting toilet", flush=True)

Entry Python Docs


22
2017-10-21 17:23



Mengapa tidak mencoba menggunakan file unbuffered?

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

ATAU

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

17
2018-04-12 10:57



import sys
print 'This will be output immediately.'
sys.stdout.flush()

12
2017-12-12 07:46



Ide Dan tidak cukup berhasil:

#!/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"

Hasil:

Traceback (most recent call last):
  File "./passpersist.py", line 12, in <module>
    print "foo"
ValueError: I/O operation on closed file

Saya percaya masalahnya adalah ia mewarisi dari kelas file, yang sebenarnya tidak diperlukan. Menurut dokumen untuk sys.stdout:

stdout dan stderr tidak perlu built-in   objek file: objek apa pun dapat diterima   asalkan memiliki metode write ()   yang mengambil argumen string.

jadi berubah

class flushfile(file):

untuk

class flushfile(object):

membuatnya bekerja dengan baik.


10
2017-11-13 22:15



Ini adalah versi saya, yang menyediakan writelines () dan fileno (), juga:

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

6
2018-05-19 08:20