Pythonでstderrに出力する方法は?


1339

stderrに書き込む方法はいくつかあります。

# Note: this first one does not work in Python 3
print >> sys.stderr, "spam"

sys.stderr.write("spam\n")

os.write(2, b"spam\n")

from __future__ import print_function
print("spam", file=sys.stderr)

それは禅のPython#13 と矛盾しているように見えるので、ここでの違いは何であり、いずれにしても長所と短所はありますか?どちらの方法を使用する必要がありますか?

明確な方法は1つ(できれば1つだけ)あるはずです。


46
リストされている最初の方法は、Python 3で削除された多くのものの1つです。コンセンサスは、>>構文がとにかく醜いということであり、printは関数なので、構文は機能しません。
スティーブハワード

24
私が使用します。sys.exit( 'エラー:<エラーテキスト>')
スターク

1
印刷を使用してください。
PythonMaster202

回答:


1164

私はこれが唯一の短い+フレキシブル+ポータブル+読み取り可能であることがわかりました:

from __future__ import print_function
import sys

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

この関数eprintは、標準print関数と同じように使用できます。

>>> print("Test")
Test
>>> eprint("Test")
Test
>>> eprint("foo", "bar", "baz", sep="---")
foo---bar---baz

29
これは印刷機能をインポートするため、元のスクリプトの他のすべての「印刷」に「(」と「)」を追加して「機能化」する必要があります。つまり、この方法に対するわずかなストライキです(IMO)。
Dan H

46
@DanHはいこの、あなたのコードがのpython3-準備をします。これが実際に多くの人が気に入っている理由だと思います!
MarcH 2014年

18
@MarkH ...はい、あなたはあなたのコードをPython3対応にすることを強制します...それはまたあなたにそれを今強制します、ただいくつかのデバッグ情報をstderrに出力するだけです...私はもっと面倒なことを見つけるでしょう何かをデバッグしようとしているほとんどの状況。(新しい構文エラーは導入しません!):-)
Dan H

30
FWIWこのコードprint、プログラム全体での関数バージョンの使用を強制しません。の定義を含むモジュール内のみeprint()。それ自体を小さなファイルに入れ、そこeprintから他のファイルにインポートすれば、必要なだけステートメントprintを使い続けることができます。
アレクシス

4
また、印刷から印刷機能への変換は、2to3が既に自動化している単純な検索置換です。まだ行っていない場合は、すでに行ってください。python2は2年足らずで消えてしまいます... 2から3の間のいくつかのことは少しトリッキーになる可能性があります。印刷機能はそれらの1つではありません。docs.python.org/2/library/2to3.htmlを
bobpaul

548
import sys
sys.stderr.write()

私の選択ですが、もっと読みやすく、意図したとおりに正確に言って、バージョン間で移植できます。

編集:「pythonic」であることは、読みやすさとパフォーマンスについての私にとって3番目の考えです...これら2つのことを念頭に置いて、pythonでは、コードの80%がpythonicになります。理解度があまり使われない「読みやすい」「大きなこと」であることを理解してください。


88
フラッシュすることを忘れないでください。
手元

10
このprintステートメントの利点は、文字列以外の値を、最初に変換する必要なく簡単に出力できることです。したがって、印刷ステートメントが必要な場合は、3番目のオプションを使用してpython 3対応にすることをお勧めします
vdboor

56
sys.stderr.write()のようなものではありませんprint。改行は追加されません。
大佐パニック

41
@temoto-stderrはバッファーされないため、フラッシュする必要はありません。
Matt

11
あなた@SkipHuffman意味os.linesepstderr結局のところ、これは私たちが話していることです。コンソールが間違った改行で混乱しないようにしてください。
jpmc26 2015

182

print >> sys.stderrPython3ではなくなりました。 http://docs.python.org/3.0/whatsnew/3.0.html言う:

Old: print >> sys.stderr, "fatal error"
New: print("fatal error", file=sys.stderr)

私たちの多くにとって、目的地をコマンドの最後に任せるのは少し不自然に感じられます。代替

sys.stderr.write("fatal error\n")

よりオブジェクト指向に見え、ジェネリックから特定のものにエレガントに移行します。ただし、これwriteはの1対1の置き換えではありませんprint


6
それは好みの問題だと思いますが、何が醜いのかわかりませんprint('spam', file=sys.stderr)。何度も繰り返している場合は、最も一般的な回答のように「eprint」関数をコーディングできますが、その場合、ロギングの何が問題になっていますか?stackoverflow.com/a/41304513/1450294
Michael Scheper 2018年

1
インテントを明確にする別の方法はwith sys.stderr as dest:、インデントされた呼び出しの前に行うことですprint("ERROR", file=dest)
MarkHu '26

131

loggingまだ誰も言及していませんが、ロギングは特にエラーメッセージを伝えるために作成されました。基本構成では、stderrに書き込むストリームハンドラーをセットアップします。

このスクリプト:

# foo.py
import logging

logging.basicConfig(format='%(message)s')
log = logging.getLogger(__name__)
log.warning('I print to stderr by default')
print('hello world')

コマンドラインで実行すると、次の結果になります。

$ python3 foo.py > bar.txt
I print to stderr by default

また、bar.txtには、標準出力に印刷された「hello world」が含まれます。


3
私の経験では、ロギングを使用するよりも、印刷を使用してメッセージをログに記録する人が多くなっています。私はpython4が言語からprintを削除し、そのためにロギングを使用することを強制するべきだと思います。
Mnebuerquo 2018年

1
これがベストアンサーです!! ...私は印刷物やシステムに苦労していた、または誰が知っているか...適切なロギングが必要な場合...良いアイデアに感謝
カルロス・サルトス

129

以下のためのPython 2私の選択がある: print >> sys.stderr, 'spam' あなたは、単に文字列に変換することなく、など、それをリスト/ dictsを印刷することができますので。 print >> sys.stderr, {'spam': 'spam'} の代わりに: sys.stderr.write(str({'spam': 'spam'}))


6
辞書を印刷するよりPython的な方法は、"{0}".format({'spam': 'spam'})とにかく何かのようなものでしょうか?明示的に文字列に変換することは避けるべきだと思います。編集:誤って文法を変更しました
luketparkinson

2
@luketparkinsonこれはすべてデバッグに関するものです。ですから、できるだけ単純なコードを使用する方が望ましいと思います。
フランコフスキーボグダン2013

88
これはPython 3では機能しないため、新しいコードでは回避する必要があります。
JonnyJD 2013

33

私はPython 3を使用して次のことを行いました。

from sys import stderr

def print_err(*args, **kwargs):
    print(*args, file=stderr, **kwargs)

したがって、たとえば、キャリッジリターンを回避するために、キーワード引数を追加できます。

print_err("Error: end of the file reached. The word ", end='')
print_err(word, "was not found")

2
パーシャルも使用できると提案しましたが、パーシャルはパーシャルの作成時にstderrを関数に割り当てることに気付きました。これにより、パーシャルがまだ元のstderrオブジェクトを保持しているため、後でstderrをリダイレクトできなくなります。
Rebs

31

あなたの最初のアプローチは:

print >> sys.stderr, 'spam' 

「一つ。。。で明らかにそれを行うための方法」他の人がルール#1満たしていない(「美しいが良い醜い超えています。」)


109
意見は異なります。これは私には最も明白ではありません。
porgarmingduod

4
@AliVeli括弧はありません。これは古いPython <= 2構文であるため、Python 3互換ではありません。
Rebs

30
これは3つすべての中で最も醜いバージョンだと思います
火山

4
>>構文的にはどういう意味ですか?私>はそれがbashをコピーするための努力であることを理解しています、それでそれを行うためのいくつかの靴角構文ですか?
Dmytro Sirenko、2014

2
@EarlGrayそれは、C ++のストリーム挿入演算子からホールドオーバだ:std::cout << "spam";
ショーン・オールレッド

19

これは標準の印刷機能を模倣しますが、標準エラー出力に出力されます

def print_err(*args):
    sys.stderr.write(' '.join(map(str,args)) + '\n')

8
私はsys.stderr.flush()を追加します
AMS

5
@AMS-なぜですか?printフラッシュは含まれません。
Robᵩ

4
あなたが実際にそれを行うことができるのになぜ模倣するのですか?
Mad Physicist、

19

Python 3では、print()を使用できます

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

ほとんど箱から出して:

import sys
print("Hello, world!", file=sys.stderr)

または:

from sys import stderr
print("Hello, world!", file=stderr)

これは簡単で、他に何も含める必要はありませんsys.stderr


16

編集後から見ると、sys.stderrを変更して動作が更新されないのと混乱する可能性があるため、この答えは、他の人が指摘している単純な関数を使用するだけでは不十分だと思います。

パーシャルのみを使用すると、コードを1行節約できます。混乱の可能性は1行のコードを保存する価値はありません。

元の

さらに簡単にするために、ここでは「部分的」を使用するバージョンを示します。これは、関数のラッピングに非常に役立ちます。

from __future__ import print_function
import sys
from functools import partial

error = partial(print, file=sys.stderr)

次に、それをそのように使用します

error('An error occured!')

次のようにして、stdoutではなくstderrに出力されていることを確認できます(http://coreygoldberg.blogspot.com.au/2009/05/python-redirect-or-turn-off-stdout-andからコードを上書きする.html):

# over-ride stderr to prove that this function works.
class NullDevice():
    def write(self, s):
        pass
sys.stderr = NullDevice()

# we must import print error AFTER we've removed the null device because
# it has been assigned and will not be re-evaluated.
# assume error function is in print_error.py
from print_error import error

# no message should be printed
error("You won't see this error!")

これの欠点は、作成時にラップされた関数にsys.stderrの値を部分的に割り当てることです。つまり、後でstderrをリダイレクトしても、この機能には影響しません。 stderrをリダイレクトする場合は、このページのaaguirreで言及されている** kwargsメソッドを使用してください。


Corey GoldbergのコードはRube Goldbergマシンで実行するのが最適ですか?:P
Agi Hammerthief 2015年

2
ところで:「部分的」についてもっと知りたい場合、「カレー」は(より)便利な検索キーワードです。
MarcH 2015

5

同じことがstdoutにも当てはまります。

print 'spam'
sys.stdout.write('spam\n')

他の回答で述べたように、printはかなり便利なインターフェース(デバッグ情報の印刷など)を提供しますが、書き込みはより高速で、出力を特定の方法で正確にフォーマットする必要がある場合にも便利です。保守性も検討します。

  1. 後でstdout / stderrと通常のファイルを切り替えることもできます。

  2. Python 3ではprint()構文が変更されているため、両方のバージョンをサポートする必要がある場合は、write()の方が適している場合があります。


4
使い方from __future__ import print_function3.両方のPython 2.6+とPythonをサポートするためのより良い方法をされた
鳳凰

4

私はpython 3.4.3で作業しています。私は私がここにたどり着いた方法を示す少しタイピングを切り取っています:

[18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ python3
>>> import sys
>>> print("testing", file=sys.stderr)
testing
>>>
[18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ 

うまくいきましたか?stderrをファイルにリダイレクトして、何が起こるかを確認してください。

[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ python3 2> /tmp/test.txt
>>> import sys
>>> print("testing", file=sys.stderr)
>>> [18:22 jsilverman@JSILVERMAN-LT7 pexpect]$
[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ cat /tmp/test.txt
Python 3.4.3 (default, May  5 2015, 17:58:45)
[GCC 4.9.2] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
testing

[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$

ええと、Pythonが提供する小さな紹介がstderrに組み込まれているという事実(他にどこに行くのでしょうか)は別として、それは機能します。


2

簡単なテストを行う場合:

import time
import sys

def run1(runs):
    x = 0
    cur = time.time()
    while x < runs:
        x += 1
        print >> sys.stderr, 'X'
    elapsed = (time.time()-cur)
    return elapsed

def run2(runs):
    x = 0
    cur = time.time()
    while x < runs:
        x += 1
        sys.stderr.write('X\n')
        sys.stderr.flush()
    elapsed = (time.time()-cur)
    return elapsed

def compare(runs):
    sum1, sum2 = 0, 0
    x = 0
    while x < runs:
        x += 1
        sum1 += run1(runs)
        sum2 += run2(runs)
    return sum1, sum2

if __name__ == '__main__':
    s1, s2 = compare(1000)
    print "Using (print >> sys.stderr, 'X'): %s" %(s1)
    print "Using (sys.stderr.write('X'),sys.stderr.flush()):%s" %(s2)
    print "Ratio: %f" %(float(s1) / float(s2))

sys.stderr.write()が一貫して1.81倍高速であることがわかります。


これを実行すると、差ははるかに小さくなります。興味深いのは、ほとんどの回答が印刷機能(Python 3)の方法を無視していることです。私はこれまで(慣性)使用したことがありませんが、このタイミングスクリプトを実行して印刷機能を追加すると思いました。printステートメントと関数を直接比較することはできません(将来のインポートはファイル全体に適用され、printステートメントをマスクします)。 )印刷機能を優先します。
ハミッシュ

1
このテストの結果は、何となく誤解を招くものです。「X」の代わりに「XXXXXXXXXXXXXXXXXXXX」を印刷すると、比率は1.05に下がります。ほとんどのpythonプログラムでは、1文字以上を印刷する必要があると思います。
2013年

15
警告の出力など、パフォーマンスは気にしません。
WIM

私はそれがしばらくの間知っているが、あなたは私の投稿の後に同様に長い間返信しました...あなたがパフォーマンスについて気にしないのであれば、私がpython.stderr.writeを使用して、WTFではなくpython.stderr.writeを使用することをお勧めしますか?!?「>>」の文字。このsys.stdout名前空間が長すぎる場合は、名前を変更できます(つまり、sys import stderrをstderr_fhとして)。その後、stderr_fh.write( "blah")を実行できます
ThePracticalOne 14

1
[3/3]このベンチマークがより正確であったとしても、心配する価値はないでしょう。Knuthが書いたように、「プログラマーはプログラムの重要ではない部分の速度について考えたり心配したりすることに膨大な時間を費やしており、これらの効率化の試みは実際にデバッグと保守を考えると強い否定的な影響を与えます。効率は、時間の約97%と言います。時期尚早の最適化がすべての悪の根源です。」
Corey Goldberg

1

致命的なエラーのためにプログラムを終了したい場合は、次を使用します。

sys.exit("Your program caused a fatal error. ... description ...")

import sysヘッダー。


-2

質問への回答は次のとおりです。Pythonでstderrを印刷する方法はいくつかありますが、それは1.)使用しているpythonのバージョンに依存しています。

printとstderrの書き込み関数の違い: stderr:stderr(標準エラー)はすべてのUNIX / Linuxシステムに組み込まれているパイプであり、プログラムがクラッシュしてデバッグ情報(Pythonのトレースバックなど)を出力すると、stderrに送られますパイプ。

print:printは、入力をフォーマットするラッパー(入力は引数と最後の改行の間のスペースです)であり、指定されたオブジェクトの書き込み関数を呼び出します。指定されたオブジェクトはデフォルトではsys.stdoutですが、ファイルを渡します。つまり、入力をファイルに出力することもできます。

Python2:python2を使用している場合

>>> import sys
>>> print "hi"
hi
>>> print("hi")
hi
>>> print >> sys.stderr.write("hi")
hi

Python2の末尾のコンマはPython3でパラメーターになるため、印刷後の改行を回避するために末尾のコンマを使用すると、Python3ではこれはprint( 'Text to print'、end = '')のようになります。これはPython2での構文エラーです。

http://python3porting.com/noconv.html

上記のシナリオをpython3で確認すると、次のようになります。

>>> import sys
>>> print("hi")
hi

Python 2.6では、関数に出力するための将来のインポートがあります。したがって、構文エラーやその他の違いを回避するために、将来のインポートprint_function でprint()を使用するファイルを開始する必要があります。将来のインポートはPythonの2.6で動作し、後で、そうはPython 2.5およびそれ以前のための2つのオプションがあります。より複雑な印刷をより単純なものに変換するか、Python2とPython3の両方で機能する別の印刷関数を使用できます。

>>> from __future__ import print_function
>>> 
>>> def printex(*args, **kwargs):
...     print(*args, file=sys.stderr, **kwargs)
... 
>>> printex("hii")
hii
>>>

ケース:sys.stderr.write()またはsys.stdout.write()(stdout(標準出力)は、すべてのUNIX / Linuxシステムに組み込まれているパイプです)は、印刷の代わりにはなりませんが、はい場合によっては、代替として使用できます。Printは、最後にスペースと改行で入力をラップし、write関数を使用して書き込むラッパーです。これがsys.stderr.write()の方が速い理由です。

注: Loggingを使用してトレースおよびデバッグすることもできます

#test.py
import logging
logging.info('This is the existing protocol.')
FORMAT = "%(asctime)-15s %(clientip)s %(user)-8s %(message)s"
logging.basicConfig(format=FORMAT)
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logging.warning("Protocol problem: %s", "connection reset", extra=d)

https://docs.python.org/2/library/logging.html#logger-objects

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