Probleme de freeze lors de dialogue avec des subprocess

Le
LB
Bonjour,

Je suis en train d'essayer de faire tourner des scripts python qui
marchait sur une station IBM AIX sur des PC linux plus récent et je me
heurte à des freezes de python.

La station AIX qui hébergeait ces scripts fonctionne sous Python 2.2
(#1, Feb 17 2003, 21:43:03) [C] on aix4.
Le PC sur lequel je souhaiterait migrer ces scripts fonctionne sous
Python 2.4.3 (#1, Jun 11 2009, 14:09:37).

La partie du code qui semble poser pb est la suivante :

[ code 1 ]
from os import popen3

f_in, f_out, f_err = popen3(cmd)
self.f_in = f_in
self.f_out = f_out
self.f_err = f_err

# Envoi des commandes
self.f_in.write('-1 ')
self.f_in.flush()

# lecture des sorties
while True
line = self.f_out.readline()
line = line.strip()
if line.startswith('F') : break
[/code 1]

Sur le PC Linux, le code freeze lamentablement.
Si l'on ajoute un print entre les dernières lignes on observe que
f_out freeze avant que l'on ait vu la fin de la sortie de cmd.

un bref test shell montre que le pb ne vient pas de la commande. La
commande suivante donne bien le résultat attendu.
echo -e '-1 ' | cmd > test.out


J'ai essayé d'utiliser subprocess au lieu de popen3, et de mettre un
fichier physique en sortie comme décrit dans
http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is=
-your-enemy/
:

[ code 2 ]
import subprocess

self.f_out = file('sortie.out', 'w+')

self.cmd = subprocess.Popen( cmd,
stdin=subprocess.PIPE, stdout=self.f_out)

self.f_in = self.cmd.stdin
self.f_err = self.cmd.stderr

# Envoi des commandes
self.f_in.write('-1 ')
self.f_in.flush()

while True :
line = self.f_out.readline()
line = line.strip()
if line.statrtswith('F') : break
[/code 2]

J'ai essayé de jouer sur l'option bufsize de Popen, mais je n'ai pas
observé de changement.
J'avoue que je n'ai pas vraiment compris ce qu'il fallait mettre dans
cette option.


Avez-vous des idées pour résoudre ce problème ?

Merci d'avance.
Cordialement,

--
LB
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Alain Ketterlin
Le #23579291
LB
[ code 1 ]
from os import popen3

f_in, f_out, f_err = popen3(cmd)
self.f_in = f_in
self.f_out = f_out
self.f_err = f_err

# Envoi des commandes
self.f_in.write('n-1nn n')
self.f_in.flush()



self.f_in.close()


# lecture des sorties
while True
line = self.f_out.readline()
line = line.strip()
if line.startswith('F') : break
[/code 1]



A mon avis, il faut fermer l'entrée du fils, sinon il n'y a pas vraime nt
de raison que le fils ne garde pas des données dans son buffer à lui (et
ton script ne peut rien faire pour cela).

Mais passer à Popen serait une bonne idée quand même.

-- Alain.
LB
Le #23580961
A mon avis, il faut fermer l'entrée du fils, sinon il n'y a pas vraimen t
de raison que le fils ne garde pas des données dans son buffer à lui (et
ton script ne peut rien faire pour cela).



Malheureusement, le script initial ne se contentait pas d'envoyer une
seule commande et je ne peux pas fermer l'entrée du fils dès la
premiere commande.
cmd est un processus qui lit des commande dans son entrée standrad et
ecrit les résultats correspondants dans son stdout :
le script python initial envoyait de nouvelles commandes selon les
réponses reçues.
Il s'agit donc d'un vrai dialogue entre les deux process et pas d'une
sucession de question-réponses indépendantes.

Mais passer à Popen serait une bonne idée quand même.



Ma tentative (cf [code 2] ) n'a pas montré de comportement différent
entre popen3 et Popen vis-à-vis de mon problème.

Précisons que le fichier test.out généré avec la commande shell ci-
dessous pèse 40 Ko et ne me semble donc pas être vraiment limitant

-- Alain.
Alain Ketterlin
Le #23581221
LB
A mon avis, il faut fermer l'entrée du fils, sinon il n'y a pas vra iment
de raison que le fils ne garde pas des données dans son buffer à   lui (et
ton script ne peut rien faire pour cela).



Malheureusement, le script initial ne se contentait pas d'envoyer une
seule commande et je ne peux pas fermer l'entrée du fils dès la
premiere commande.
cmd est un processus qui lit des commande dans son entrée standrad et
ecrit les résultats correspondants dans son stdout :
le script python initial envoyait de nouvelles commandes selon les
réponses reçues.
Il s'agit donc d'un vrai dialogue entre les deux process et pas d'une
sucession de question-réponses indépendantes.



Ce que je disais est : ça ne peut pas marcher, puisque ça dé pend de la
façon dont *le fils* gère sa sortie. Si il utilise stdio (ce qui est
probablement le cas), il peut très bien garder la fin de sa répon se dans
son buffer. Donc il faudra peut-être que tu envoies une deuxième
commande pour récupérer la fin de la réponse à la premi ère (et même
peut-être le début de la réponse à la deuxième).

Mais passer à Popen serait une bonne idée quand même.



Ma tentative (cf [code 2] ) n'a pas montré de comportement diffà ©rent
entre popen3 et Popen vis-à-vis de mon problème.



Ce n'était pas sensé résoudre la problème, juste é viter de tomber sur un
bug non corrigé d'une bibliothèque non maintenue.

Précisons que le fichier test.out généré avec la comm ande shell ci-
dessous pèse 40 Ko et ne me semble donc pas être vraiment limit ant



Pas d'importance. Il faut vérifier comment le fils utilise sa sortie.
C'est lui qui doit faire flush() (aussi).

-- Alain.
Publicité
Poster une réponse
Anonyme