2012-05-02 9 views
18

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

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

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"]) 

>>の構文は私にとってよく知られているわけではありません。頻繁に使用するものではありません。おそらくleast preferred wayがstderrに書き込まれていることを理解しています。しかし、代替案が根本的な問題を解決するとは思わない。

私が読んだドキュメントから、IOError 5はしばしば誤って使用され、やや緩やかに定義されています。さまざまなオペレーティングシステムを使用してさまざまな問題をカバーしています。私が私のケースで見ることができる最高ののは、Pythonのプロセスがもはや端末/ ptyに接続されていないということです。

stdout/stderrストリームからプロセスを切断することは何も言えません。端末はまだ開いていますが、すべてが正常であると表示されます。それは、子プロセスが不正な方法で終了することによって引き起こされる可能性がありますか?この問題の原因は他に何か - それをさらにデバッグするために私が何を紹介することができますか?

例外処理に関しては、明らかにそれをキャッチすることができますが、これは残りの実行のためにstdout/stderrに印刷できないことを意味しています。これらのストリームに何らかの形で再接続できますか?おそらくsys.stdoutsys.__stdout__などにリセットしますか?この場合、stdout/stderrに書き込むことができないということは致命的とはみなされませんが、何かが間違って始まることを示すものであれば、私はむしろ早く退会したいと思います。

私は、私は非常によく似た問題を抱えていた

+1

この質問を閲覧した人はほんの数人しかいないことがわかります。コメントや回答はありません。質問の構成が不十分/不明な場合は、改善に役立てて回答に向けて作業してください。 –

+0

私はこのエラーも解消しています。だから時々このエラーを得るのは面倒です。 –

+1

いくつかの返事について悪いと感じないでください。あなたの質問とフォーマットは素晴らしいです。これは単に答えが難しい質問です。 – culix

答えて

5

...最終的に私はこの1つのデバッグを開始する場所へと損失のビットで思いますよ。私は、サブプロセスモジュールを使用していくつかの他のプログラムを起動していたプログラムを持っていました。これらのサブプロセスは、出力を端末に出力します。私が見つけたのは、メインプログラムを閉じたときに、自動的にサブプロセスを終了させず、実行し続けていたということでした。したがって、メインプログラムとそれから起動された端末の両方を終了した場合、サブプロセスは端末をstdoutに接続しなくなり、IOErrorがスローされます。これがあなたを助けることを願ってください。

* NB:この順番で行う必要があります。ターミナルを殺すだけなら(何らかの理由で)、メインプログラムとサブプロセスの両方が殺されます。

+1

私の状況にはあなたの説明が意味がありますが、質問が残っています。ドキュメントによれば、ファイルの終わりに達するまで、()の呼び出しは、サブプロセスが終了するのを待つ。通常の実行中にこのエラーが発生するので(私は親プロセスと子プロセスの両方を自然に終了させて​​います)、それはcommunications()が早期に戻ることを意味しますか? –

2

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

+0

いいえ、残念ながらそうではありません。使用可能なディスク容量が十分にあり、明らかに最大ファイルハンドル制限に達していない、CPU負荷が低く、スワップしていない。 –

10

処理が付いている端末と関係があると思います。私は、バックグラウンドでのpythonのプロセスを実行すると、このエラーを持って、私はそれを開始した端末を閉じた状態:

$ myprogram.py 
Ctrl-Z 
$ bg 
$ exit 

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

0

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

0

私はここで新しくなっていますので、コードの詳細についてはちょっと説明してください。 最近、pythonスクリプトの実行に関連する端末が閉じられたときに、printステートメントのI/Oエラーの原因を突き止めることができました。 stdout/stderrに出力する文字列が長すぎるためです。この場合、「out」文字列が原因です。 この問題を解決するには(pythonスクリプトの実行中に端末を開いたままにする必要はありません)、 "out"文字列を行単位で読み込み、 "out"文字列の終わりに達するまで行単位で印刷します。次のようなものがあります。

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

文字列の一覧全体を画面に印刷すると同じ問題が発生します。リストを1つのアイテムだけ印刷するだけです。 希望に役立ちます!