印刷機能の出力をフラッシュする方法は?
-
04-07-2019 - |
質問
Pythonの印刷機能を強制的に画面に出力するにはどうすればよいですか
これは出力バッファリングを無効にするの複製ではありません-リンクされた質問はバッファリングされていない状態です出力ですが、これはより一般的です。この質問の上位の回答は、この質問には強力すぎるか、関与しすぎており(これに対する適切な回答ではありません)、この質問はGoogleで比較的初心者によって見つけることができます。
解決
import sys
sys.stdout.flush()
print
デフォルトでは、sys.stdout
に出力されます。
参照
Python 2
Python 3
-
flush
-
io.IOBase
- ファイルオブジェクト-用語集
- <=> (<=>継承<=>)からの<=>メソッド
他のヒント
python -h
を実行すると、コマンドラインオプションが表示されます:
-u:バッファリングされていないバイナリstdoutおよびstderr。 PYTHONUNBUFFERED = xも '-u'に関連する内部バッファリングの詳細については、manページを参照してください
関連ドキュメントです。
Python 3.3以降では、print()
を使用せずに通常のsys.stdout.flush()
関数を強制的にフラッシュできます。 <!> quot; flush <!> quotを設定するだけです。 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の場合、ストリームは強制的にフラッシュされます。
Python印刷の出力をフラッシュする方法
これを行うには5つの方法をお勧めします:
- Python 3では、
print(..., flush=True)
を呼び出します(フラッシュ引数は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(または<!> lt; 3.3)
flush
引数をPython 2.7にバックポートしなかったため、Python 2(または3.3未満)を使用していて、2と3の両方と互換性のあるコードが必要な場合、次の互換性コードを提案できます。 (__future__
インポートは/ very <!> quot; モジュールのトップ <!> quot;):
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ステートメントを使用して、印刷後に<=>を呼び出すこともできます。
import sys
print 'delayed output'
sys.stdout.flush()
1つのモジュールのデフォルトを<=>
に変更するモジュールのグローバルスコープで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
再度、これは現在のグローバルスコープを変更するだけです。現在のグローバルスコープの印刷名は組み込みの<=>関数を覆い隠します(または、現在のグローバルスコープでPython 2を使用している場合は互換性関数を間接参照します)。
モジュールのグローバルスコープではなく関数内でこれを行う場合は、別の名前を付ける必要があります。例:
def foo():
printf = functools.partial(print, flush=True)
printf('print stuff like this')
関数でグローバルとして宣言する場合、モジュールのグローバル名前空間でそれを変更しているので、その特定の動作がまさにあなたの望むものでない限り、単にグローバル名前空間に置くべきです。
プロセスのデフォルトの変更
ここでの最良のオプションは、バッファなしの出力を取得するために<=>フラグを使用することだと思います。
$ python -u script.py
または
$ python -um package.module
ドキュメントから:
stdin、stdout、およびstderrを強制的に完全にバッファリング解除します。重要なシステムでは、stdin、stdout、stderrもバイナリモードにします。
このオプションの影響を受けないfile.readlines()およびファイルオブジェクト(sys.stdinの行用)には内部バッファリングがあることに注意してください。これを回避するには、while 1:ループ内でfile.readline()を使用します。
シェル操作環境のデフォルトの変更
環境変数を空でない文字列に設定すると、1つまたは複数の環境内のすべてのpythonプロセスでこの動作を取得できます。
e.g。、LinuxまたはOSXの場合:
$ export PYTHONUNBUFFERED=TRUE
またはWindows:
C:\SET PYTHONUNBUFFERED=TRUE
ドキュメントから:
PYTHONUNBUFFERED
これが空でない文字列に設定されている場合、-uオプションを指定することと同等です。
広告デンダム
Python 2.7.12のprint関数に関するヘルプがあります- no <=>引数があることに注意してください:
>>> 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が必要です<!>#8217; t組み込み ファイルオブジェクト:任意のオブジェクトが受け入れられます write()メソッドがある限り 文字列引数を取ります。
変化している
class flushfile(file):
to
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...')