21

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

执行以下 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"])

语法对>>我来说不是特别熟悉,它不是我经常使用的东西,而且我知道它可能是写入 stderr的最不受欢迎的方式。但是,我不相信替代方案可以解决根本问题。

从我读过的文档来看,IOError 5 经常被误用,而且定义有些松散,不同的操作系统使用它来解决不同的问题。在我的情况下,我能看到的最好的结果是 python 进程不再附加到终端/pty。

尽我所知,没有什么可以断开进程与 stdout/stderr 流的连接——例如,终端仍处于打开状态,并且一切“似乎”都很好。这可能是由子进程以不干净的方式终止引起的吗?还有什么可能是导致此问题的原因 - 或者我可以引入哪些其他步骤来进一步调试它?

在处理异常方面,我显然可以捕捉到它,但我假设这意味着我将无法在剩余的执行过程中打印到 stdout/stderr?我可以以某种方式重新连接到这些流 - 也许通过重置sys.stdoutsys.__stdout__?在这种情况下,无法写入 stdout/stderr 并不被认为是致命的,但如果它表明某些事情开始出错,我宁愿早点保释。

我想最终我对从哪里开始调试这个有点不知所措......

4

7 回答 7

14

我认为这与进程所连接的终端有关。当我在后台运行 python 进程并关闭启动它的终端时出现此错误:

$ myprogram.py
Ctrl-Z
$ bg
$ exit

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

于 2014-01-08T13:53:14.200 回答
6

我有一个非常相似的问题。我有一个程序正在使用 subprocess 模块启动其他几个程序。然后这些子进程会将输出打印到终端。我发现当我关闭主程序时,它并没有自动终止子进程(正如我所假设的那样),而是它们继续运行。因此,如果我终止了主程序,然后终止了它启动的终端*,则子进程不再有终端连接到它们的标准输出,并且会抛出一个 IOError。希望这对您有所帮助。

*注意:必须按此顺序完成。如果您只是杀死终端,(出于某种原因)会杀死主程序和子进程。

于 2012-07-27T15:17:51.460 回答
2

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

于 2012-12-22T15:26:33.490 回答
1

我是新来的,所以如果我在代码细节方面有点疏忽,请原谅。最近,当与运行 python 脚本相关的终端关闭时,我能够找出导致打印语句 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

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

于 2017-02-10T23:21:03.973 回答
1

问题是你已经关闭了python 在被调用stdout时试图写入的管道print()

这可能是由于在后台使用&然后关闭终端会话(即关闭stdout)运行脚本引起的

$ python myscript.py &
$ exit

一种解决方案是stdout在后台运行时设置为文件

例子

$ python myscript.py > /var/log/myscript.log 2>&1 &
$ exit

没有错误print()

于 2021-01-13T20:11:04.033 回答
0

当您的 shell 在 print 试图将数据写入其中时崩溃时,可能会发生这种情况。

于 2016-04-14T20:36:05.423 回答
0

就我而言,我只是重新启动服务,然后这个问题就消失了。现在不知道为什么。对于 Odoo,我的问题是相同的 OSError 输入/输出错误。

我重新启动服务后,它就消失了。

于 2020-04-01T00:03:49.710 回答