我继承了一些代码,这些代码周期性地(随机地)失败,因为在调用打印时出现了输入/输出错误。我正在试图确定引发异常的原因(或者至少更好地理解它)以及如何正确地处理它。
在执行以下python行时(在2.6.6解释器中,在CentOS 5.5上运行):
1print >> sys.stderr, 'Unable to do something: %s' % command
引发异常(省略了回溯):
1IOError: [Errno 5] Input/output error
对于上下文,这通常是较大的函数在当时要做的事情:
1
2
3
4
5
6
7
8
9
10
11
12from 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并不是致命的,但如果这是开始出错的迹象,我宁愿提前保释。
我想最终我对从哪里开始调试这个有点迷茫…
我只能看到少数人看过这个问题,没有评论/回答。如果问题结构不好/不清楚,请帮助我改进它,以便我能找到答案。
我也将此错误过期。有时犯这个错误真让人恼火。
回答很少,别难过;你的问题和格式很好;这只是一个很难回答的问题。
那么,运气好吗?我在multiprocessing模块上也遇到了同样的错误,并且我的数据被篡改了。
@查理-不,不幸的是不是。这里的答案都不太适合或解释我的用例。这是我学会与之共处的东西。
我认为这与流程所附的终端有关。当我在后台运行一个python进程并关闭启动它的终端时,我得到了这个错误:
1
2
3
4$ myprogram.py
Ctrl-Z
$ bg
$ exit
问题是我在远程服务器中启动了一个非守护进程并注销(关闭终端会话)。解决方案是在远程服务器上启动screen/tmux会话,并在此会话中启动进程。然后,分离会话+注销将保留与进程关联的终端。这至少在尼克斯世界中有效。
我在一个远程服务器上有同样的问题脚本,它打印到stdout。当我通过ssh连接时工作正常,但是当我在打印之前注销时,代码会引发一个ioerror。这个类似的问题也有一个很好的答案。
我也遇到了类似的问题。我有一个使用子进程模块启动其他几个程序的程序。然后这些子进程将输出打印到终端。我发现当我关闭主程序时,它不会自动终止子进程(正如我所假定的那样),而是继续运行。因此,如果我同时终止了主程序,然后终止了从*启动的终端,子进程就不再有一个终端连接到它们的stdout,并且会抛出一个ioerror。希望这对你有帮助。
*注意:必须按此顺序进行。如果您只是终止终端,(出于某种原因),那么会同时终止主程序和子进程。
你所描述的对我的情况来说是有意义的,不过还有一个问题。根据文档,对communication()的调用应该读取到文件末尾,然后等待子进程终止。当我在正常执行过程中得到这个错误时(我让父进程和子进程都自然终止),这是否意味着communication()提前返回?
我刚收到这个错误是因为我写文件的目录内存不足。不确定这是否完全适用于您的情况。
不,不幸的是不是。大量可用磁盘空间,显然未达到最大文件句柄限制、低CPU负载和无交换。
我是新来的,所以请原谅我在涉及到代码细节时有点滑倒。最近,当与python脚本的运行相关联的终端关闭时,我能够找出print语句的I/O错误的原因。这是因为要打印到stdout/stderr的字符串太长。在这种情况下,"out"字符串是罪魁祸首。要解决这个问题(在运行python脚本时不需要保持终端打开),只需逐行读取"out"字符串,然后逐行打印,直到到达"out"字符串的末尾。类似:
1
2
3
4
5while true:
ln=out.readline()
if not ln: break
print ln.strip("
") # print without new line
如果将字符串的整个列表打印到屏幕上,也会出现同样的问题。只需逐个打印列表。希望有帮助!
我可以证实。将更大的有效载荷倾倒到分离的终端上确实会引发错误。我想当stdd将数据发送到终端时,套接字有效负载的大小是问题所在。
它可能发生在你的外壳崩溃时,而打印试图写入它的数据。