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

bizarreries avec sleep et while (1)

4 réponses
Avatar
gvdmoort
Bonjour =E0 tous,

J'ex=E9cute ceci

#!/usr/bin/perl
use strict;
while (1) {
print ". ";
# sleep 1;
}

et comme attendu, mon terminal se couvre de petits points.
J'interrompt avec Ctl-c

Je d=E9commente la ligne avec le sleep, j'ex=E9cute le script... et rien
ne se passe, le curseur reste immobile.

Je fais un Ctl-c, j'ajoute un \n =E0 la cha=EEne

print ". \n";

et le r=E9sultat est bien un point par ligne =E0 intervalle d'une seconde.

Je ne comprends absolument pas, qu'est-ce qui explique =E7a ? (Inutile
de pr=E9ciser que la chose se d=E9roulait avec un script plus =E9labor=E9 e=
t
que j'ai pass=E9 un temps fou =E0 en trouver la raison...)

Pour aller plus loin, qu'est-ce qui pourrait remplacer cette
construction rudimentaire pour lancer une fonction =E0 intervalle
r=E9gulier ?

while (1) {
&faire_quelque_chose
sleep 15;
}

Comme la fonction s'ex=E9cute en un temps variable, l'intervalle
s'allonge et l'ex=E9cution se d=E9cale dans le temps; comme elle collecte
des donn=E9es que je souhaite int=E9grer d

4 réponses

Avatar
gvdmoort
(Désolé, envoi intempestif)

Comme la fonction s'exécute en un temps variable, l'intervalle
s'allonge d'autant et l'exécution se décale dans le temps; comme elle
collecte
des données que je souhaite intégrer dans un graphe, j'aimerais que
l'intervalle reste constant.

Merci d'avance,

Gauthier
Avatar
YBM
gvdmoort a écrit :
Pour aller plus loin, qu'est-ce qui pourrait remplacer cette
construction rudimentaire pour lancer une fonction à intervalle
régulier ?

while (1) {
&faire_quelque_chose
sleep 15;
}



#!/usr/bin/perl
use strict;
while (1) {
local $|=1;
print ". ";
sleep 1;
}

perldoc perlvar pour la signification de $|
Avatar
YBM
gvdmoort a écrit :
(Désolé, envoi intempestif)

Comme la fonction s'exécute en un temps variable, l'intervalle
s'allonge d'autant et l'exécution se décale dans le temps; comme elle
collecte
des données que je souhaite intégrer dans un graphe, j'aimerais que
l'intervalle reste constant.



Dans ce cas, il faut procéder autrement en programmant un signal
(grossièrement) périodique :

#!/usr/bin/perl

use strict;
use warnings;

local $SIG{ALRM} = sub { local $|=1; print '. '; alarm(1); };
alarm(1);

while (1) { # remplace cette boucle par ton traitement.

}

Attention : l'utilisation de cette méthode empêche d'utiliser sleep();
dans le script.
Avatar
Paul Gaborit
À (at) Tue, 18 May 2010 12:15:51 -0700 (PDT),
gvdmoort écrivait (wrote):

J'exécute ceci

#!/usr/bin/perl
use strict;
while (1) {
print ". ";
# sleep 1;
}

et comme attendu, mon terminal se couvre de petits points.
J'interrompt avec Ctl-c

Je décommente la ligne avec le sleep, j'exécute le script... et rien
ne se passe, le curseur reste immobile.

Je fais un Ctl-c, j'ajoute un n à la chaîne

print ". n";

et le résultat est bien un point par ligne à intervalle d'une seconde.

Je ne comprends absolument pas, qu'est-ce qui explique ça ? (Inutile
de préciser que la chose se déroulait avec un script plus élaboré et
que j'ai passé un temps fou à en trouver la raison...)



La sortie standard est bufferisée (ou tamponnée pour parler français)
par ligne si elle est reliée à un terminal et par bloc sinon. Dans le
cas d'un terminal, tout ce qu'on y écrit n'est réellement envoyé que
lorsqu'on y écrit un passage à la ligne ou lorsque le tampon est plein.

Pour répondre au souci ci-dessus, soit on fait appel à flush soi-même
pour forcer le vidage du tampon :

use IO::Handle;
while(1) {
print ".";
STDOUT->flush;
sleep 1;
}

soit on utilise 'autoflush' sur STDOUT pour que le vidage ait lieu à
chaque écriture :

use IO::Handle;
autoflush STDOUT 1;
while(1) {
print ".";
sleep 1;
}

--
Paul Gaborit - <http://perso.mines-albi.fr/~gaborit/>
Perl en français - <http://perl.mines-albi.fr/>