web-dev-qa-db-ja.com

印刷時のIOError入出力エラー

Printの呼び出し中に入出力エラーが発生したために定期的(ランダム)に失敗するコードを継承しました。発生している例外の原因(または、少なくともそれをよりよく理解している)と、それを正しく処理する方法を特定しようとしています。

Pythonの次の行を実行すると(CentOS 5.5で実行されている2.6.6インタープリター)):

print >> sys.stderr, 'Unable to do something: %s' % command

例外が発生します(トレースバックは省略されます)。

IOError: [Errno 5] Input/output error

コンテキストについては、これは一般に、より大きな関数がその時に実行しようとしていることです。

from subprocess import Popen, PIPE
import sys
def run_commands(commands):
    for command in commands:
        try:
            out, err = Popen(command, Shell=True, stdout=PIPE, stderr=PIPE).communicate()
            print >> sys.stdout, out
            if err:
                raise Exception('ERROR -- an error occurred when executing this command: %s --- err: %s' % (command, err))
        except:
            print >> sys.stderr, 'Unable to do something: %s' % command
run_commands(["ls", "echo foo"])

>>構文は私には特に馴染みがなく、私が頻繁に使用するものではありません。それはおそらく、stderrへの書き込みの 最も望ましい方法 であることを理解しています。しかし、私は代替案が根本的な問題を解決するとは信じていません。

私が読んだドキュメンテーションから、IOError 5はしばしば誤用され、いくぶん大まかに定義されており、さまざまなオペレーティングシステムがさまざまな問題をカバーするためにそれを使用しています。私のケースで私が見ることができる最高のものは、pythonプロセスがもはやterminal/ptyにアタッチされていないことです。

最善の策として、プロセスをstdout/stderrストリームから切断することは何もないことがわかります。たとえば、ターミナルはまだ開いており、すべて正常に表示されます。子プロセスが不明瞭な方法で終了したことが原因である可能性がありますか?他に何がこの問題の原因である可能性がありますか-またはそれをさらにデバッグするために他にどのような手順を導入できますか?

例外の処理に関して、私は明らかにそれをキャッチできますが、これは、残りの実行でstdout/stderrに出力できないことを意味していると思いますか?これらのストリームに何らかの方法で再接続できますか-sys.stdoutからsys.__stdout__など?この場合、stdout/stderrに書き込めないことは致命的とは見なされませんが、何かがうまくいかなくなったことを示している場合は、早めに保釈したいと思います。

私は最終的に、これをどこからデバッグし始めるかについて少し途方に暮れていると思います...

20

プロセスが接続されている端末に関係していると思います。 pythonプロセスをバックグラウンドで実行し、それを開始したターミナルを閉じると、このエラーが発生しました:

$ myprogram.py
Ctrl-Z
$ bg
$ exit

問題は、リモートサーバーでデーモン化されていないプロセスを開始し、ログアウトした(ターミナルセッションを閉じた)ことです。解決策は、リモートサーバーでscreen/tmuxセッションを開始し、このセッション内でプロセスを開始することでした。次に、セッションとログアウトを切り離しても、端末はプロセスに関連付けられたままになります。これは少なくとも* nixの世界では機能します。

12
jmkg

私は非常に似た問題を抱えていました。サブプロセスモジュールを使用して他のいくつかのプログラムを起動するプログラムがありました。これらのサブプロセスは、出力をターミナルに出力します。私が見つけたのは、メインプログラムを閉じたときに、サブプロセスが(想定していたように)自動的に終了せず、実行を続けているということでした。したがって、メインプログラムとそれが起動された端末の両方を終了した場合、サブプロセスにはstdoutに接続された端末がなくなり、IOErrorがスローされます。これがお役に立てば幸いです。

*注:この順序で実行する必要があります。ターミナルを強制終了すると、(何らかの理由で)メインプログラムとサブプロセスの両方が強制終了されます。

6
gtg944q

ファイルを書き込んでいるディレクトリでメモリ不足が発生したため、このエラーが発生しました。これがあなたの状況にまったく当てはまるかどうかはわかりません。

2
zss

私はここに新しく来たので、コードの詳細に関して少しずれた場合はご容赦ください。最近、pythonスクリプトの実行に関連付けられているターミナルが閉じられたときに、printステートメントのI/Oエラーの原因を突き止めることができました。これは、出力される文字列がstdout/stderrが長すぎます。この場合、「out」文字列が原因です。この問題を修正するには(pythonスクリプトを実行している間、ターミナルを開いたままにしておく必要はありません)、単に「out」文字列を1行ずつ出力し、「out」文字列の終わりに到達するまで1行ずつ出力します。

while true:
        ln=out.readline()
        if not ln: break
        print ln.strip("\n") # print without new line

文字列のリスト全体を画面に出力すると、同じ問題が発生します。リストを1アイテムずつ印刷するだけです。お役に立てば幸いです。

1
Thang

これは、印刷がデータを書き込もうとしたときにシェルがクラッシュしたときに発生する可能性があります。

0
mtmt

私の場合、サービスを再起動するだけで、この問題は消えます。今は理由はありません。私の問題は、OdooのOSError入出力エラーと同じでした。

サービスを再起動すると、サービスが消えました。

0
Robin LI