web-dev-qa-db-fra.com

Erreur d'entrée/sortie IOError lors de l'impression

J'ai hérité d'un code qui échoue périodiquement (de manière aléatoire) en raison d'une erreur d'entrée/de sortie générée au cours d'un appel à imprimer. J'essaie de déterminer la cause de l'exception levée (ou du moins de mieux la comprendre) et comment la gérer correctement.

Lors de l'exécution de la ligne suivante de Python (dans un interpréteur 2.6.6 s'exécutant sur CentOS 5.5):

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

L'exception est levée (traceback omitted):

IOError: [Errno 5] Input/output error

Pour le contexte, c’est généralement ce que la fonction principale essaie de faire à l’époque:

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

La syntaxe >> ne m'est pas particulièrement familière, ce n'est pas quelque chose que j'utilise souvent et je comprends que c'est peut-être la méthode la moins préférée d'écrire sur stderr. Cependant, je ne crois pas que les solutions de rechange permettraient de résoudre le problème sous-jacent.

D'après la documentation que j'ai lue, IOError 5 est souvent mal utilisé, et défini de manière assez vague, avec différents systèmes d'exploitation qui l'utilisent pour couvrir différents problèmes. Le mieux que je puisse voir dans mon cas est que le processus python n’est plus lié au terminal/pty.

Autant que je sache, rien ne déconnecte le processus des flux stdout/stderr - le terminal est toujours ouvert, par exemple, et tout semble "bien". Cela pourrait-il être causé par la fin du processus enfant d'une manière impure? Quoi d'autre pourrait être une cause de ce problème - ou quelles autres étapes pourrais-je introduire pour le déboguer davantage?

En termes de gestion de l'exception, je peux évidemment l'attraper, mais je suppose que cela signifie que je ne pourrai pas imprimer sur stdout/stderr pour le reste de l'exécution? Puis-je me rattacher à ces flux d'une manière ou d'une autre - peut-être en rétablissant sys.stdout en sys.__stdout__ etc.? Dans ce cas, ne pas être capable d'écrire sur stdout/stderr n'est pas considéré comme fatal, mais si cela indique que quelque chose commence à aller de travers, je préfère partir tôt.

Je suppose que finalement je ne sais pas trop par où commencer le débogage de celui-ci ...

20

Je pense que cela a à voir avec le terminal auquel le processus est attaché. J'ai eu cette erreur lorsque j'ai exécuté un processus python en arrière-plan et que j'ai fermé le terminal dans lequel je l'ai démarré:

$ myprogram.py
Ctrl-Z
$ bg
$ exit

Le problème était que j'ai démarré un processus non démonisé sur un serveur distant et que je me suis déconnecté (fermeture de la session de terminal). Une solution consistait à démarrer une session screen/tmux sur le serveur distant et à démarrer le processus au cours de cette session. Ensuite, le détachement de la session + déconnexion maintient le terminal associé au processus. Cela fonctionne au moins dans le monde * nix.

12
jmkg

J'ai eu un problème très similaire. J'avais un programme qui lançait plusieurs autres programmes en utilisant le module de sous-processus. Ces sous-processus imprimeraient ensuite la sortie vers le terminal. Ce que j'ai trouvé, c'est que lorsque j'ai fermé le programme principal, les sous-processus ne se sont pas arrêtés automatiquement (comme je l'avais supposé), ils ont continué à fonctionner. Donc, si je terminais à la fois le programme principal, puis le terminal à partir duquel il avait été lancé, les sous-processus n’avaient plus de terminal attaché à leur sortie standard, et jetteraient un IOError. J'espère que cela vous aide.

* NB: cela doit être fait dans cet ordre. Si vous ne faites que tuer le terminal, (pour une raison quelconque), cela tuerait à la fois le programme principal et les sous-processus.

6
gtg944q

Je viens de recevoir cette erreur parce que le répertoire dans lequel j'écrivais des fichiers était à court de mémoire. Vous ne savez pas si cela s'applique à votre situation.

2
zss

Je suis nouveau ici, alors pardonnez-moi si je perds un peu de temps en ce qui concerne les détails du code. Récemment, j’ai été en mesure de comprendre la cause de l’erreur d’entrée/sortie de l’instruction print lorsque Le script Python est fermé. C'est parce que la chaîne à imprimer sur stdout/stderr est trop longue. Dans ce cas, le coupable est la chaîne "out". Pour résoudre ce problème (sans avoir à garder le terminal ouvert pendant l'exécution du script python), il suffit de lire la chaîne "out" ligne par ligne et de la ligne par ligne, jusqu'à la fin de la chaîne "out". Quelque chose comme:

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

Le même problème se produit si vous imprimez la liste complète des chaînes à l'écran. Imprimez simplement la liste un article par un. Espérons que cela aide!

1
Thang

Cela peut se produire lorsque votre Shell se bloque alors que l’impression essayait d’écrire les données.

0
mtmt