印刷機能の出力をフラッシュする方法は?


1216

Pythonの印刷機能を強制的に画面に出力するにはどうすればよいですか?

これはDisable output bufferingの複製ではありません-これはより一般的ですが、リンクされた質問はバッファリングされていない出力を試みています。その質問の上位の回答は強力すぎるか、この質問に関与しています(これは適切な回答ではありません)。この質問は、比較的初心者がGoogleで見つけることができます。

回答:


1428

Python 3ではprint、オプションのflush引数を取ることができます

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

Python 2ではあなたがしなければならないでしょう

import sys
sys.stdout.flush()

呼び出しprintた後。デフォルトでは、にprint出力されますsys.stdoutファイルオブジェクトの詳細については、ドキュメントを参照してください)。


347

実行するpython -hと、コマンドラインオプションが表示されます

-u:バッファリングされていないバイナリstdoutおよびstderr; また、PYTHONUNBUFFERED = x「-u」に関連する内部バッファリングの詳細については、manページを参照してください。

こちらが関連ドキュメントです。


320

Python 3.3以降でprint()は、を使用せずに通常の関数を強制的にフラッシュできますsys.stdout.flush()。「flush」キーワード引数をtrueに設定するだけです。ドキュメントから:

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

オブジェクトをsepで区切られ、その後にendが続くストリームファイルに出力します。sep、end、およびfile(存在する場合)は、キーワード引数として指定する必要があります。

キーワード以外のすべての引数は、str()のように文字列に変換されてストリームに書き込まれ、sepで区切られ、その後にendが続きます。sepとendは両方とも文字列でなければなりません。Noneにすることもできます。これは、デフォルト値を使用することを意味します。オブジェクトが指定されていない場合、print()はendを書き込みます。

file引数は、write(string)メソッドを持つオブジェクトでなければなりません。存在しないかNoneの場合、sys.stdoutが使用されます。出力がバッファリングされるかどうかは通常ファイルによって決定されますが、flushキーワード引数がtrueの場合、ストリームは強制的にフラッシュされます。


198

Python printの出力をフラッシュする方法は?

これを行う5つの方法をお勧めします。

  • Python 3で呼び出しますprint(..., flush=True)(flush引数はPython 2のprint関数では使用できません。また、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()たとえばPython 2のprintステートメントを使用して、印刷後に呼び出すこともできます。

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

1つのモジュールのデフォルトを flush=True

モジュールのグローバルスコープでfunctools.partialを使用して、print関数のデフォルトを変更できます。

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の行)には内部バッファリングがあることに注意してください。これを回避するには、while 1:ループ内でfile.readline()を使用します。

シェル動作環境のデフォルトを変更する

環境変数を空でない文字列に設定すると、環境内のすべてのpythonプロセス、または環境から継承する環境でこの動作を得ることができます。

たとえば、LinuxまたはOSXの場合:

$ export PYTHONUNBUFFERED=TRUE

またはWindows:

C:\SET PYTHONUNBUFFERED=TRUE

ドキュメントから:

PYTHONUNBUFFERED

これが空でない文字列に設定されている場合、-uオプションを指定することと同じです。


補遺

Python 2.7.12のprint関数のヘルプを次に示します- 引数がない ことに注意して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「フラッシュ引数は、Python 3.3(印刷後の()将来のインポートを介して2.7にバックポートされた)を添加した」ためbugs.python.org/issue28458
オリバー・

69

また、このブログで提案されているようにsys.stdout、バッファなしモードで再開できます。

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

stdout.writeand print操作はその後自動的にフラッシュされます。


2
Ubuntu 12.04のpython 2.7では、これは私に与えますUnsupportedOperation: IOStream has no fileno.
drevicko

3
おっと、Python 3が見つかりました。このコードを実行することはできません!
EKons

この慣用句に戸惑っています。これを行った後、2つのFile-likeオブジェクト(元のsys.stdoutと新しいsys.stdout)はどちらもfilenoを「所有」していると考えていませんか?それは悪いですよね?
ドンハッチ


36

-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編集されます。


4
ファイルから継承しないで、追加してstdoutに委任することをお勧めします。def __getattr__(self,name): return object.__getattribute__(self.f, name)
2013年

2
@diedthreetimesのコメントで提案された変更がないと、「ValueError:閉じたファイルでのI / O操作」が
発生し

19

バッファリングされていないファイルを使用してみませんか?

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

または

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

1
彼はバッファリングされていないファイルを作成したくありません。彼は、既存のstdout(コンソール、ターミナルなどにリダイレクトされます。これを変更してはいけません)をバッファーなしにしたいと考えています。
blueFast 2015

13

ダンのアイデアはまったく機能しません。

#!/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):

うまく機能します。


17
これは
@Dan

8

これが私のバージョンで、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クラスはありません。
コリンDベネット

6

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)

2
他のすべての高品質の応答を考えると、この答えは少し軽いようです。あなたはそれにもう少し追加したいと思うかもしれません。
セミコロンとダクトテープ2016

5

私はそれをPython 3.4でこのようにしました:

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

2

最初に、フラッシュオプションがどのように機能しているかを理解するのに苦労しました。私は「ローディング表示」をしたいと思っていました、そしてここに私が見つけた解決策があります:

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

1行目は前の出力をフラッシュし、2行目は新しく更新されたメッセージを出力します。ここに1行の構文が存在するかどうかはわかりません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.