关于python:ioerror打印时的输入/输出错误

IOError Input/Output Error When Printing

我继承了一些代码,这些代码周期性地(随机地)失败,因为在调用打印时出现了输入/输出错误。我正在试图确定引发异常的原因(或者至少更好地理解它)以及如何正确地处理它。

在执行以下python行时(在2.6.6解释器中,在CentOS 5.5上运行):

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

引发异常(省略了回溯):

1
IOError: [Errno 5] Input/output error

对于上下文,这通常是较大的函数在当时要做的事情:

1
2
3
4
5
6
7
8
9
10
11
12
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最不喜欢的书写方式。然而,我不相信替代方案能解决根本问题。

从我读过的文档中,IOERROR5经常被误用,并且定义得有点松散,不同的操作系统使用它来解决不同的问题。在我的例子中,我能看到的最好的一点是python进程不再连接到终端/pty。

据我所知,没有什么是从stdout/stderr流断开进程的连接——例如,终端仍然处于打开状态,所有"似乎"都正常。这可能是由以不干净的方式终止的儿童进程引起的吗?还有什么可能是导致这个问题的原因-或者我可以引入什么其他步骤来进一步调试它?

在处理异常方面,我显然可以捕捉到它,但我假设这意味着在剩余的执行期间,我将无法打印到stdout/stderr?我能以某种方式重新连接到这些流吗?可能是通过将sys.stdout重置为sys.__stdout__等?在这种情况下,无法写入stdout/stderr并不是致命的,但如果这是开始出错的迹象,我宁愿提前保释。

我想最终我对从哪里开始调试这个有点迷茫…


我认为这与流程所附的终端有关。当我在后台运行一个python进程并关闭启动它的终端时,我得到了这个错误:

1
2
3
4
$ myprogram.py
Ctrl-Z
$ bg
$ exit

问题是我在远程服务器中启动了一个非守护进程并注销(关闭终端会话)。解决方案是在远程服务器上启动screen/tmux会话,并在此会话中启动进程。然后,分离会话+注销将保留与进程关联的终端。这至少在尼克斯世界中有效。


我也遇到了类似的问题。我有一个使用子进程模块启动其他几个程序的程序。然后这些子进程将输出打印到终端。我发现当我关闭主程序时,它不会自动终止子进程(正如我所假定的那样),而是继续运行。因此,如果我同时终止了主程序,然后终止了从*启动的终端,子进程就不再有一个终端连接到它们的stdout,并且会抛出一个ioerror。希望这对你有帮助。

*注意:必须按此顺序进行。如果您只是终止终端,(出于某种原因),那么会同时终止主程序和子进程。


我刚收到这个错误是因为我写文件的目录内存不足。不确定这是否完全适用于您的情况。


我是新来的,所以请原谅我在涉及到代码细节时有点滑倒。最近,当与python脚本的运行相关联的终端关闭时,我能够找出print语句的I/O错误的原因。这是因为要打印到stdout/stderr的字符串太长。在这种情况下,"out"字符串是罪魁祸首。要解决这个问题(在运行python脚本时不需要保持终端打开),只需逐行读取"out"字符串,然后逐行打印,直到到达"out"字符串的末尾。类似:

1
2
3
4
5
while true:
        ln=out.readline()
        if not ln: break
        print ln.strip("
"
) # print without new line

如果将字符串的整个列表打印到屏幕上,也会出现同样的问题。只需逐个打印列表。希望有帮助!


它可能发生在你的外壳崩溃时,而打印试图写入它的数据。