web-dev-qa-db-ja.com

Print関数の出力をフラッシュするにはどうすればいいですか?

Pythonのprint関数を画面に出力させるにはどうすればいいですか?

出力バッファリングを無効にする - リンクされた質問がバッファリングされていない出力を試みているが、これはより一般的である。その質問の一番上の答えはあまりにも強力であるか、この質問には関係しています(これはあまり良い答えではありません)。この質問は比較的初心者の方でもGoogleで見つけることができます。

1013
Walter Nissen
import sys
sys.stdout.flush()

printはデフォルトでsys.stdoutに出力されます。

参考文献

Python 2

Python 3

1196
CesarB

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

-u:バッファなしのバイナリ標準出力と標準エラー出力。 PYTHONUNBUFFERED = x -uに関する内部バッファリングの詳細についてはmanページを参照してください。

これは 関連ドキュメント です。

320
gimel

Python 3.3以降、print()を使わなくても通常のsys.stdout.flush()関数をフラッシュさせることができます。 "flush"キーワード引数をtrueに設定するだけです。 から

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

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

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

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

290
Eugene Sajine

Pythonの出力をフラッシュするにはどうすればいいですか?

私はこれをする5つの方法を提案する:

  • Python 3では、print(..., flush=True)を呼び出します(flush引数はPython 2のprint関数では使用できません。printステートメントに類似するものはありません)。
  • 出力ファイルに対してfile.flush()を呼び出します(これを行うためにpython 2のprint関数をラップすることができます)、例えばsys.stdout
  • 部分的な関数を持つモジュール内のすべてのprint関数呼び出しにこれを適用します。
    print = partial(print, flush=True)がモジュールグローバルに適用されました。
  • インタプリタコマンドにフラグ(-u)を渡してプロセスに適用する
  • PYTHONUNBUFFERED=TRUEを使用して環境内のすべてのpythonプロセスにこれを適用します(そしてこれを元に戻すために変数の設定を解除します)。

Python 3.3以降

Python 3.3以降を使用して、print関数へのキーワード引数としてflush=Trueを提供することができます。

print('foo', flush=True) 

Python 2(または<3.3)

彼らはPython 2.7のflush引数をバックポートしませんでした。もしあなたがPython 2(あるいは3.3以下)を使っていて、2と3の両方と互換性のあるコードが欲しいなら、私は以下の互換性コードを提案します。 (__future__インポートは/非常に "あなたのモジュールの top "の近くになければなりません):

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モジュールを見てください

あるいは、たとえばPython 2のprint文を使用して、印刷後にfile.flush()を呼び出すこともできます。

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

docs :から

標準入力、標準出力、標準エラー出力を完全にバッファなしにします。重要なシステムでは、標準入力、標準出力、標準エラー出力をバイナリモードにしてください。

このオプションの影響を受けないfile.readlines()とファイルオブジェクト(sys.stdinの行)には内部バッファがあります。これを回避するには、while 1:ループ内でfile.readline()を使用します。

Shellオペレーティング環境のデフォルトを変更する

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

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

$ export PYTHONUNBUFFERED=TRUE

またはWindows:

C:\SET PYTHONUNBUFFERED=TRUE

docs :から

_ pythonunbuffered _

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


補遺

これはPython 2.7.12のprint関数に関するヘルプです - noflush引数があることに注意してください。

>>> 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.
146
Aaron Hall

また このブログで示唆されているように oneはバッファなしモードでsys.stdoutを開くことができます:

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

それぞれのstdout.writeおよびprint操作はその後自動的にフラッシュされます。

66

Python 3.xではprint()関数が拡張されました。

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

だから、あなたはただすることができます:

print("Visiting toilet", flush=True)

Python Docs Entry

49
Noah Krasser

-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を暗黙的に使用)が自動的にflushedになります。

34
Dan Lenski

バッファされていないファイルを使ってみませんか?

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

OR

sys.stdout = open('out.log', 'a', 0)
18
Frank
import sys
print 'This will be output immediately.'
sys.stdout.flush()
14
Dynamic

Danの考えはあまりうまくいきません。

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

それはうまく動作します。

12
Kamil Kisiel

これが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()
7
guettli

ダンの解決策が大好き! 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)
6
Jonas Byström

Python 3では、デフォルトをflush = Trueに設定してprint関数を上書きすることができます

def print(*objects, sep=' ', end='\n', file=sys.stdout, flush=True):
    __builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)
3
user263387

私はPython 3.4ではこんな感じでした。

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