Python には既知の問題があり、stdout で「パイプの破損」が発生すると「ファイル オブジェクト デストラクタでクローズに失敗しました」という問題があります - Python トラッカーの問題 11380 ; Pythonでも見られる- 私の Python3 スクリプトは、出力を先頭または末尾 (sys モジュール) にパイプするのをためらうのはなぜですか? - スタック オーバーフロー。
私がやりたいのは、Python 2.7 と Python 3+ の両方で、この問題が発生したときに同じカスタム メッセージを出力することです。そこで、テスト スクリプトを準備して実行します ( Ubuntu 11.04testprint.py
で実行されたスニペットを示します)。bash
$ cat > testprint.py <<"EOF"
import sys
def main():
teststr = "Hello " * 5
sys.stdout.write(teststr + "\n")
if __name__ == "__main__":
main()
EOF
$ python2.7 testprint.py
Hello Hello Hello Hello Hello
$ python2.7 testprint.py | echo
close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
$ python3.2 testprint.py | echo
Exception IOError: (32, 'Broken pipe') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> ignored
上記のリンクから予想されるように、2 つの異なるメッセージがあります。Help with a pipe error (velocityreviews.com)では、 sys.stdout.flush()
Python 2 にそのメッセージの代わりに IOError を強制的に登録させるために使用することをお勧めします。これで、次のようになります。
$ cat > testprint.py <<"EOF"
import sys
def main():
teststr = "Hello " * 5
sys.stdout.write(teststr + "\n")
sys.stdout.flush()
if __name__ == "__main__":
main()
EOF
$ python2.7 testprint.py | echo
Traceback (most recent call last):
File "testprint.py", line 9, in <module>
main()
File "testprint.py", line 6, in main
sys.stdout.flush()
IOError: [Errno 32] Broken pipe
$ python3.2 testprint.py | echo
Traceback (most recent call last):
File "testprint.py", line 9, in <module>
main()
File "testprint.py", line 6, in main
sys.stdout.flush()
IOError: [Errno 32] Broken pipe
Exception IOError: (32, 'Broken pipe') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> ignored
さて、これらの例外を「無視」する (または、私の場合は、カスタム エラー メッセージに置き換える) 方法は、それらを処理することです。
> [インタープリター] に例外を無視させる方法はありますか?
いいえ。例外を処理するか、例外を生成しないコードを記述してください。
... そして、Python の紹介 - 例外の処理のメモのように、それを行う方法は try/except ブロックです。それでは、それを試してみましょう:
$ cat > testprint.py <<"EOF"
import sys
def main():
teststr = "Hello " * 5
try:
sys.stdout.write(teststr + "\n")
sys.stdout.flush()
except IOError:
sys.stderr.write("Exc: " + str(sys.exc_info()[0]) + "\n")
if __name__ == "__main__":
main()
EOF
$ python2.7 testprint.py | echo
Exc: <type 'exceptions.IOError'>
$ python3.2 testprint.py | echo
Exc: <class 'IOError'>
Exception IOError: (32, 'Broken pipe') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> ignored
OK、try/except は Python 2.7 で期待どおりに動作しますが、Python 3.2 は両方とも期待どおりに処理し、メッセージを生成しException ... ignored
ます! 何が問題なのですか? " except IOError
" では Python 3 には十分ではありませんか? しかし、そうでなければなりませんExc:...
。
では、ここでの問題は何Exception ... ignored
ですか。また、例外を処理しているにもかかわらず、Python 3 でまだ印刷されているのはなぜですか? さらに重要なことは、印刷されないException ... ignored
ようにするにはどうすればよいですか?