IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Sortie de boucle trop tôt


Sujet :

Langage Perl

  1. #1
    Membre régulier
    Inscrit en
    Juin 2005
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 243
    Points : 89
    Points
    89
    Par défaut Sortie de boucle trop tôt
    Bonjour,

    J'ai un problème assez simple à résoudre, et pourtant j'ai passé pas mal de temps dessus. Ainsi je viens ici en quête d'aide.

    J'ai fait un script en Perl qui prend un nombre en paramètre. Imaginons 5.

    Le script va pourcourir une liste d'IP, puis va modifier le statut de chacune d'elle en base.

    Il va le faire pour les 5 premières, puis attendre 30 secondes. Il va alors checker leur nouveau statut. Si c'est à "Done" alors il va pouvoir libérer une place dans le slot d'IP à traiter (ici 5). En gros il ne doit pas y avoir plus de 5 IP en cours de traitement.

    L'algo que j'ai fait suivi du code mis en place actuellement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
     
    Foreach MesIP :
           UpdateEnBaseDuStatus
           Ajout de l'Id de l'IP dans le tableau @IdTodoRouter
     
    If ($IpBatch = ($IpBatch - $FreeSlot) {#Si Nombre Max à traiter (ici 5) = (5 - FreeSlot)
         Do{
              Sleep(30);
              my $i;
              Foreach (@IdTodoRouter){
              my $NewStatus = rechercheNewStatus($IdTodoRouter[$i]);
              ## Free Detection :
              if ($NewStatus = "Done") {
                   $FreeSlot++;
                   $NbIp--;
                   Print "ID : " $IdTodoRouter[$i]." est à Done";
                   @IdTodoRouter = delete_Tab ($i,@IdTodoRouter); ### Supprime l Id du tableau
              elsif ($NewStatus = "Doing") {
                   Print "ID : " $IdTodoRouter[$i]." est à Doing"; 
                   $i++;
             }
             while ($IpBatch = ($IpBatch - $FreeSlot));
    }else{
    ...
    }
    Là j'ai un bug d'affichage dans le sens où quand le script voit que j'ai une IP à "done", il va alors augmenter le nombre de FreeSlot et va donc sortir de la boucle. Hors le traitement n'est pas terminé, j'aimerai qu'il termine de lister l'état des 5 status.

    Voyez-vous comment faire cela s'il-vous-plait ? (En fait en écrivant ce post, je me dis qu'une boucle For pourrait résoudre le problème ?) Par ailleurs, si vous avez du temps pour critiquer le script en place je suis preneur.

    D'avance, merci pour votre aide et bon weekend.

  2. #2
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Aux dernières nouvelles Perl était sensible à la casse et If, Do, While n'était pas des mots clés du langage. if, do, while, print, etc marchent bien mieux.

    Ceci dit, ta structure me semble à la fois boiteuse et inefficace : y a-t-il une raison pour que tu sois obligé de procéder par paquet de 5 adresses ? Ne préférerais tu pas que ton script traite toujours 5 adresses, remplaçant immédiatement une adresse traitée par une nouvelle adresse de la queue de façon à en traiter toujours 5 à la fois tant qu'il reste des adresses à traiter ?

    Dans ce cas je te propose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    my %handledIPStatus;
     
    $handledIPStatus{shift @ipQueue} = 'None' for (1..@ipQueue > 5 ? 5 : @ipQueue);
     
    while( %handledIPStatus ) {
      foreach my $ip (keys %handledIPStatus) {
     
        if($handledIPStatus{$ip} eq 'None') {
          updateDBStatus($ip);
          $handledIPStatus{$ip} = 'Queried';
          next; # skip checking status for new ips
        }
     
        my $status = rechercheNewStatus($ip);
        print "ID : l'état de $ip est $status";
     
        if ($status eq 'Done') {
          delete $handledIPStatus{$ip};
          $handledIPStatus{shift @ipQueue} = 'None' if @ipQueue;
        }
      }
      sleep 30;
    }
    Quelque chose comme ça serait probablement plus robuste et plus efficace.
    --
    Jedaï

  3. #3
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Et ce genre de code se compile correctement?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Foreach MesIP :
           UpdateEnBaseDuStatus
           Ajout de l'Id de l'IP dans le tableau @IdTodoRouter
     
    If ($IpBatch = ($IpBatch - $FreeSlot) {#Si Nombre Max à traiter (ici 5) = (5 - FreeSlot)
         Do{
    Déjà, au moins trois erreurs sur la première ligne de code: "foreach", pas "Foreach", et probablement @MesIP ou peut être $MesIP, mais pas MesIP. Et plutôt quelque chose du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    foreach (@MesIP} {
         do something;
    }
    Les lignes suivantes ne sont guère meilleures.

    Un petit coup d’œil aux tutoriels disponibles sur ce site ne serait peut-être pas superflu.

    Edit: grillé d'une minute par Jedaï.

  4. #4
    Membre régulier
    Inscrit en
    Juin 2005
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 243
    Points : 89
    Points
    89
    Par défaut
    Bonjour à vous deux,

    Merci de vous être penché sur mon pb.

    Lolo78, en effet cela doit piquer les yeux ce que j'ai marqué, en fait le début correspond à l'algo mis en place et à partir du if, c'est le code que j'ai retapé manuellement (je n'ai pas mon code source ici). Du coup il doit en effet y avoir bcp d'erreurs.

    Jedaï, merci infiniment pour le code donné, ça m'a l'air vraiment optimum. Si vous avez un peu de temps encore à me consacrer, pourriez-vous me le détailler un petit peu SVP ? Notamment le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $handledIPStatus{shift @ipQueue} = 'None' for (1..@ipQueue > 5 ? 5 : @ipQueue);
    Je comprends qu'il va mettre dans la hash table handledIPStatus chaque IP contenu dans le tableau ipQueue et mettre la valeur "None" à chaque key, mais j'ai du mal à saisir le sens du for, j'aurais eu tendance à dire que ça allait le faire pour les 5 premiers mais en testant chez moi, il me fait le traitement que 1 à 1 ou tout d'un coup si je charge l'ensemble des IPs dans le tableau, j'ai fait la chose suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    use strict;
    my $status;
    my @ligne=();
    my @ipQueue=();
    my %handledIPStatus;
     
    open my $IN , "<", "D:\ip.txt" or die "Can't open le fichier : $!";
     
    while( <$IN> ){
    	@ligne = split(',',$_);
    	push (@ipQueue,$ligne[0]);
     
    	$handledIPStatus{shift @ipQueue} = 'None' for (1..@ipQueue > 5 ? 5 : @ipQueue);
     
    	while( %handledIPStatus ) {
    	  foreach my $ip (keys %handledIPStatus) {
    		if($handledIPStatus{$ip} eq 'None') {
    		  #updateDBStatus($ip);
    		  $handledIPStatus{$ip} = 'Queried';
    		  next; # skip checking status for new ips
    		}
     
    		my $status = rechercheNewStatus($ip);
    		print "ID : l'état de $ip est $status";
     
    		if ($status eq "Done\n") {
    		  delete $handledIPStatus{$ip};
    		  $handledIPStatus{shift @ipQueue} = 'None' if @ipQueue;
    		}
    	  }
    	  sleep 3;
    	}
    }
     
    close($IN);
     
    sub rechercheNewStatus {
    	my ($Aip) = @_;
    	my @l=();
    	open my $IN2 , "<", "D:\ip.txt" or die "Can't open le fichier : $!";
    	while( <$IN2> ){
    		#chop $_;
    		@l = split(',',$_);
    		if ($l[0] eq $Aip) {
    			return ($l[1]);			
     
    		}
    	}
    	close ($IN2);
    }
    En mettant ceci dans mon fichier text :
    0.0.0.1,Done
    0.0.0.2,Done
    0.0.0.3,Todo
    ...
    (je remplace à la main le status pour faire office de la fonction updateDBStatus).

    Voyez-vous comment je peux charger les 5 premières IPs de mon fichier dans la hash table pour démarrer le traitement sur celles-ci SVP ?

    Merci encore.

  5. #5
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Petite erreur dans le for :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $handledIPStatus{shift @ipQueue} = 'None' for ( 1 .. (@ipQueue > 5 ? 5 : scalar @ipQueue) );
    L'objectif étant d'extraire les 5 premières IPs contenues dans @ipQueue si ce tableau contient plus de 5 IPs et d'en faire 5 clés dans %handledIPStatus (avec 'None' comme valeur), s'il y a moins de 5 IPs dans @ipQueue, elle sont toutes extraites.

    Ce coup-ci le for a été testé, si tu as un problème, il ne vient pas de là.
    --
    Jedaï

  6. #6
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par Jedai Voir le message
    Petite erreur dans le for :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $handledIPStatus{shift @ipQueue} = 'None' for ( 1 .. (@ipQueue > 5 ? 5 : scalar @ipQueue) );
    Pour se faire plaisir on peut aussi écrire plus simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $handledIPStatus{$_} = 'None' foreach splice @ipQueue, 0, 5;
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

Discussions similaires

  1. Sortie de boucle trop tôt
    Par soad029 dans le forum Langage
    Réponses: 0
    Dernier message: 22/11/2014, 11h48
  2. probleme de resultat en sortie de boucle for
    Par afssaLERH dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 31/10/2007, 16h16
  3. sortie de boucle
    Par peldaine dans le forum VBScript
    Réponses: 4
    Dernier message: 18/07/2007, 13h59
  4. [debutant] boucle trop longue?
    Par dolu02 dans le forum Langage
    Réponses: 3
    Dernier message: 30/04/2007, 16h17
  5. Sortie de boucle par validation O/N
    Par kOrt3x dans le forum Ada
    Réponses: 7
    Dernier message: 08/12/2006, 03h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo