Discussion:
bizarreries avec sleep et while (1)
(trop ancien pour répondre)
gvdmoort
2010-05-18 19:15:51 UTC
Permalink
Bonjour à tous,

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...)

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;
}

Comme la fonction s'exécute en un temps variable, l'intervalle
s'allonge et l'exécution se décale dans le temps; comme elle collecte
des données que je souhaite intégrer d
gvdmoort
2010-05-18 19:19:10 UTC
Permalink
(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
YBM
2010-05-18 20:33:02 UTC
Permalink
Post by 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.
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.
YBM
2010-05-18 19:52:34 UTC
Permalink
Post by gvdmoort
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 $|
Paul Gaborit
2010-05-20 07:53:42 UTC
Permalink
À (at) Tue, 18 May 2010 12:15:51 -0700 (PDT),
Post by gvdmoort
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/>
Continuer la lecture sur narkive:
Loading...