23

I have inherited some code which is periodically (randomly) failing due to an Input/Output error being raised during a call to print. I am trying to determine the cause of the exception being raised (or at least, better understand it) and how to handle it correctly.

When executing the following line of Python (in a 2.6.6 interpreter, running on CentOS 5.5):

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

The exception is raised (traceback omitted):

IOError: [Errno 5] Input/output error

For context, this is generally what the larger function is trying to do at the time:

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

The >> syntax is not particularly familiar to me, it's not something I use often, and I understand that it is perhaps the least preferred way of writing to stderr. However I don't believe the alternatives would fix the underlying problem.

From the documentation I have read, IOError 5 is often misused, and somewhat loosely defined, with different operating systems using it to cover different problems. The best I can see in my case is that the python process is no longer attached to the terminal/pty.

As best I can tell nothing is disconnecting the process from the stdout/stderr streams - the terminal is still open for example, and everything 'appears' to be fine. Could it be caused by the child process terminating in an unclean fashion? What else might be a cause of this problem - or what other steps could I introduce to debug it further?

In terms of handling the exception, I can obviously catch it, but I'm assuming this means I wont be able to print to stdout/stderr for the remainder of execution? Can I reattach to these streams somehow - perhaps by resetting sys.stdout to sys.__stdout__ etc? In this case not being able to write to stdout/stderr is not considered fatal but if it is an indication of something starting to go wrong I'd rather bail early.

I guess ultimately I'm at a bit of a loss as to where to start debugging this one...

Community
  • 1
  • 1
Mark Streatfield
  • 3,189
  • 1
  • 22
  • 19
  • 1
    I can see only a few people have viewed this question, with no comments/answers. If the question is poorly structured/unclear, please help me improve it so I can work towards an answer. – Mark Streatfield May 05 '12 at 04:33
  • I am expiriencing this error too. So annoying to get this error sometimes. – Saša Šijak Jun 13 '12 at 13:51
  • 1
    Don't feel bad about few replies; your question and format are great; this is simply a difficult question to answer. – culix Dec 25 '13 at 07:40
  • So, any luck? I am having this same error with `multiprocessing` module and pickling my data. – Charlie Sep 19 '14 at 17:16
  • @Charlie - no, unfortunately not. None of the answers here quite fit or explain my use case. It is something I've learned to live with/work around. – Mark Streatfield Sep 28 '14 at 00:56

7 Answers7

14

I think it has to do with the terminal the process is attached to. I got this error when I run a python process in the background and closed the terminal in which I started it:

$ myprogram.py
Ctrl-Z
$ bg
$ exit

The problem was that I started a not daemonized process in a remote server and logged out (closing the terminal session). A solution was to start a screen/tmux session on the remote server and start the process within this session. Then detaching the session+log out keeps the terminal associated with the process. This works at least in the *nix world.

jmkg
  • 1,499
  • 1
  • 11
  • 10
  • I had the same issue - script in a remote server that prints to stdout. Works fine when I am connected via ssh but when I log out before it prints, the code raises an IOError. [This similar question](https://stackoverflow.com/questions/38238139/python-prevent-ioerror-errno-5-input-output-error-when-running-without-stdo) has also a very nice answer. – Jeyekomon May 22 '18 at 15:23
6

I had a very similar problem. I had a program that was launching several other programs using the subprocess module. Those subprocesses would then print output to the terminal. What I found was that when I closed the main program, it did not terminate the subprocesses automatically (as I had assumed), rather they kept running. So if I terminated both the main program and then the terminal it had been launched from*, the subprocesses no longer had a terminal attached to their stdout, and would throw an IOError. Hope this helps you.

*NB: it must be done in this order. If you just kill the terminal, (for some reason) that would kill both the main program and the subprocesses.

forsvarir
  • 10,749
  • 6
  • 46
  • 77
gtg944q
  • 61
  • 1
  • 2
  • 1
    What you describe makes sense for my situation, however a question remains. According to the docs, the call to communicate() should read until end-of-file is reached, and wait for the subprocess to terminate. As I am getting this error during normal execution (I am leaving both the parent and child process to terminate naturally) does that mean that communicate() is returning early? – Mark Streatfield Jul 31 '12 at 05:07
2

I just got this error because the directory where I was writing files to ran out of memory. Not sure if this is at all applicable to your situation.

zss
  • 335
  • 2
  • 3
  • 10
  • No, unfortunately not. Plenty of disk space available, apparently not reaching the max file handle limit, low cpu load, and no swapping. – Mark Streatfield Mar 07 '13 at 07:18
1

I'm new here, so please forgive if I slip up a bit when it comes to the code detail. Recently I was able to figure out what cause the I/O error of the print statement when the terminal associated with the run of the python script is closed. It is because the string to be printed to stdout/stderr is too long. In this case, the "out" string is the culprit. To fix this problem (without having to keep the terminal open while running the python script), simply read the "out" string line by line, and print line by line, until we reach the end of the "out" string. Something like:

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

The same problem occurs if you print the entire list of strings out to the screen. Simply print the list one item by one item. Hope that helps!

Thang
  • 21
  • 1
  • I can verify that. Dumping a bigger payload onto the detached terminal does throws the error. I guess the socket payload size is the problem here when stdd-ing the data onto the terminal. – eAlie Jan 14 '19 at 16:15
1

The problem is you've closed the stdout pipe which python is attempting to write to when print() is called

This can be caused by running a script in the background using & and then closing the terminal session (ie. closing stdout)

$ python myscript.py &
$ exit

One solution is to set stdout to a file when running in the background

Example

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

No errors on print()

Bobs Burgers
  • 761
  • 1
  • 5
  • 26
0

It could happen when your shell crashes while the print was trying to write the data into it.

mtmt
  • 173
  • 1
  • 10
0

For my case, I just restart the service, then this issue disappear. don't now why. My issue was the same OSError Input/Output error, for Odoo.

After I restart the service, it disappeared.

Robin LI
  • 41
  • 7