1608

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 †</sup> の zen と矛盾しているように見えますが、ここでの違いは何ですか? どちらか一方に利点または欠点がありますか? どの方法を使用する必要がありますか?

†</sup>それを行う明白な方法は 1 つ、できれば 1 つだけにする必要があります。

4

16 に答える 16

1405

これは、短く、柔軟で、移植可能で、読みやすい唯一のものであることがわかりました。

# This line only if you still care about Python2
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
于 2013-02-20T13:31:54.223 に答える
623
import sys
sys.stderr.write()

私の選択は、より読みやすく、何をしようとしているのかを正確に言い、バージョン間で移植可能です。

編集:「pythonic」であることは、読みやすさとパフォーマンスに関する私にとって3番目の考えです...これら2つのことを念頭に置いて、pythonを使用すると、コードの80%がpythonicになります。リスト内包表記は、それほど頻繁には使用されない「大きなもの」です (読みやすさ)。

于 2011-04-07T01:03:21.727 に答える
300

パイソン 2:

print >> sys.stderr, "fatal error"

パイソン 3:

print("fatal error", file=sys.stderr)

長い答え

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

古い:print >> sys.stderr, "fatal error"
新しい:print("fatal error", file=sys.stderr)

私たちの多くにとって、目的地をコマンドの最後に追いやることは、いくぶん不自然に感じます。代替手段

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

よりオブジェクト指向に見え、一般的なものから特定のものへとエレガントに移行します。ただし、writeは を 1:1 で置き換えるものではないことに注意してくださいprint

于 2013-04-04T10:00:16.273 に答える
171

まだ誰も言及され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には、stdout に出力される「hello world」が含まれます。

于 2016-12-23T16:04:44.133 に答える
132

Python 2の場合、私の選択は次のとおり print >> sys.stderr, 'spam' です。リスト/辞書などを文字列に変換せずに単純に印刷できるためです。 print >> sys.stderr, {'spam': 'spam'} それ以外の: sys.stderr.write(str({'spam': 'spam'}))

于 2011-11-08T17:29:52.050 に答える
49

あなたの最初のアプローチは次のとおりです。

print >> sys.stderr, 'spam' 

他の方法はルール 1 を満たしていません (「美しいことは醜いことよりも優れている」)

-- 2020年に向けて編集 --

上記は、2011 年の Python 2.7 に対する私の回答です。Python 3 が標準になった今、「正しい」回答は次のようになると思います。

print("spam", file=sys.stderr) 
于 2011-04-07T01:05:24.923 に答える
21

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

def print_err(*args):
    sys.stderr.write(' '.join(map(str,args)) + '\n')
于 2012-10-06T07:42:50.217 に答える
17

編集後から考えると、sys.stderr の変更と更新された動作が表示されないことによる潜在的な混乱により、この回答は、他の人が指摘したように単純な関数を使用するほど良くないと思います。

部分のみを使用すると、1 行のコードを節約できます。潜在的な混乱は、1 行のコードを節約する価値はありません。

オリジナル

さらに簡単にするために、'partial' を使用するバージョンを次に示します。これは、関数をラップするのに非常に役立ちます。

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 メソッドを使用してください。

于 2013-12-30T02:13:49.073 に答える
6

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

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

他の回答で述べたように、printは多くの場合より便利なきれいなインターフェイスを提供しますが (たとえば、デバッグ情報を印刷する場合)、writeは高速で、出力を特定の方法で正確にフォーマットする必要がある場合にも便利です。保守性も考慮します:

  1. 後で stdout/stderr と通常のファイルを切り替えることにするかもしれません。

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

于 2012-11-01T11:58:08.173 に答える
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 に丸呑みされているという事実は別として (他にどこに行くのでしょうか?)、それは機能します。

于 2016-02-10T02:29:27.367 に答える
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倍高速であることがわかります。

于 2012-06-12T17:17:38.713 に答える