Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Probleme de freeze lors de dialogue avec des subprocess

3 réponses
Avatar
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=E9cent et je me
heurte =E0 des freezes de python.

La station AIX qui h=E9bergeait 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 =3D popen3(cmd)
self.f_in =3D f_in
self.f_out =3D f_out
self.f_err =3D f_err

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

# lecture des sorties
while True
line =3D self.f_out.readline()
line =3D 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=E8res 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=E9sultat attendu.
echo -e '\n-1\n\n \n' | cmd > test.out


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

[ code 2 ]
import subprocess

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

self.cmd =3D subprocess.Popen( cmd,
stdin=3Dsubprocess.PIPE, stdout=3Dself.f_out)

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

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

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

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


Avez-vous des id=E9es pour r=E9soudre ce probl=E8me ?

Merci d'avance.
Cordialement,

--
LB

3 réponses

Avatar
Alain Ketterlin
LB writes:

[ 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.
Avatar
LB
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.
Avatar
Alain Ketterlin
LB writes:

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.