Подтвердить что ты не робот

Ошибка ввода/вывода 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"])

Синтаксис >> не очень мне знаком, это не то, что я часто использую, и я понимаю, что это, пожалуй, написания STDERR. Однако я не считаю, что альтернативы будут устранять основную проблему.

Из документации, которую я прочитал, IOError 5 часто неправильно используется и несколько слабо определен, при этом различные операционные системы используют его для решения различных проблем. Самое лучшее, что я вижу в моем случае, это то, что процесс python больше не привязан к терминалу /pty.

Насколько я могу сказать, ничто не отключает процесс от потоков stdout/stderr - терминал по-прежнему открыт, например, и все "отображается" в порядке. Может ли это быть вызвано тем, что дочерний процесс заканчивается нечистым образом? Что еще может быть причиной этой проблемы - или какие другие шаги я могу внести, чтобы отладить ее дальше?

Что касается обработки исключения, я, очевидно, поймаю его, но я предполагаю, что это означает, что я не смогу напечатать на stdout/stderr для остальной части исполнения? Могу ли я снова подключиться к этим потокам - возможно, сбросив sys.stdout до sys.__stdout__ и т.д.? В этом случае невозможность записи в stdout/stderr не считается фатальной, но если это указывает на то, что что-то начинает идти не так, я бы предпочел залог раньше.

Я предполагаю, что в конечном итоге я немного потеряю, где начать отладку этого...

4b9b3361

Ответ 1

Я думаю, что это связано с терминалом, к которому привязан процесс. Я получил эту ошибку, когда я запустил процесс python в фоновом режиме и закрыл терминал, в котором я его запустил:

$ myprogram.py
Ctrl-Z
$ bg
$ exit

Проблема заключалась в том, что я начал не демоннизированный процесс на удаленном сервере и вышел из системы (закрыв сеанс терминала). Решение состояло в том, чтобы запустить сеанс screen/tmux на удаленном сервере и запустить процесс в этом сеансе. Затем отсоединение сеанса + выход ведет к соединению терминала с процессом. Это работает, по крайней мере, в мире * nix.

Ответ 2

У меня была очень похожая проблема. У меня была программа, которая запускала несколько других программ, используя модуль подпроцесса. Затем эти подпроцессы будут печатать выходные данные на терминале. Я обнаружил, что когда я закрыл основную программу, она не прекращала подпроцессы автоматически (как я предполагал), скорее они продолжали работать. Поэтому, если я прекратил работу как основной программы, а затем терминала, она была запущена из *, подпроцессы больше не имели терминала, подключенного к их stdout, и выбрали бы IOError. Надеюсь, это поможет вам.

* NB: это должно быть сделано в этом порядке. Если вы просто убьете терминал (по какой-то причине), который убьет как основную программу, так и подпроцессы.

Ответ 3

Я только что получил эту ошибку, потому что в директории, где я писал файлы, закончилась нехватка памяти. Не уверен, что это вообще применимо к вашей ситуации.

Ответ 4

Это может произойти, когда ваша оболочка сработает, когда печать пытается записать в нее данные.

Ответ 5

Я новичок здесь, поэтому, пожалуйста, простите, если немного подскочить, когда дело доходит до детализации кода. Недавно мне удалось выяснить причину ошибки ввода-вывода оператора печати, когда терминал, связанный с запуском python script, закрыт. Это потому, что строка, которая будет напечатана в stdout/stderr, слишком длинная. В этом случае виновником является строка "out" . Чтобы устранить эту проблему (не закрывая терминал при запуске python script), просто прочитайте строку "out" по строкам и напечатайте строку за строкой, пока мы не дойдем до конца строки "out" . Что-то вроде:

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

Такая же проблема возникает, если вы распечатываете весь список строк на экране. Просто распечатайте список по одному элементу по одному элементу. Надеюсь, что это поможет!