bizarreries avec sleep et while (1)

Le
gvdmoort
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 à la chaîne

print ". ";

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é e=
t
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
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
gvdmoort
Le #22135721
(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
Le #22136001
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 $|
YBM
Le #22136221
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.
Paul Gaborit
Le #22142281
À (at) Tue, 18 May 2010 12:15:51 -0700 (PDT),
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 - Perl en français -
Publicité
Poster une réponse
Anonyme