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

Modules Perl Discussion :

robustesse, gestion des exceptions ? (Error.pm, Fatal.pm)


Sujet :

Modules Perl

  1. #1
    Membre habitué

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Points : 142
    Points
    142
    Par défaut robustesse, gestion des exceptions ? (Error.pm, Fatal.pm)
    voilà, j'utilise NET::FTP pour faire du téléchargement de masse avec traitement derrière. j'ai eu cette erreur :
    Timeout at c:/Perl/lib/Net/FTP.pm line 503
    qui correspond à
    last unless $len=$data->read($buf,$blksize)
    bref... c'est assez ennuyeux que le script s'arrête brutalement en killant les threads qui sont derrière, en ne finissant pas les logs comme il faut...
    je me demandais si il n'y a pas un moyen de catcher les erreurs comme par exemple la gestion des exceptions en Java. Je viens de voir qu'il existait Error.pm ou même Fatal.pm qui semblent gérer les exceptions. Je n'ai pas trouvé beaucoup de doc dessus, ça semble assez récent et peut être pas vraiment abouti...
    quelqu'un a-t'il déjà utilisé les Exceptions en perl ?
    que puis je faire pour éviter mon problème de TimeOut ? suis je obligé de modifier la source du problème (FTP.pm) en levant des exceptions (throw) ou puis je catcher directement les "problemes" avec un use Fatal.pm ?
    merci de me faire partager votre expérience
    ++

    PS : lorsque l'on a plusieurs Threads est ce que si un d'eux gère un problème cela ne perturbe pas trop les autres ?

    PS2 (pas la console ) : j'ai pas trouvé la liste des exceptions de base... si quelqu'un a le lien...

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    427
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 427
    Points : 459
    Points
    459
    Par défaut
    normalement l'errur que tu decrit doit venir d'un 'die "Timeout"' ou 'croak "Timeout"' et non simplement d'un last.

    Pour catcher les erreur en perl on utilise eval {} (la versions avec des acollades, pas celles avec des guillemets de preference)
    c'est un peu l'equivalent d'un try:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    eval {
        1==0 || die "erreur";
    };
    et ensuite tu peux faire ton catch en testant la variable $@, qui contiendra l'erreur (en string) si erreur il y a:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    eval {
        1==0 || die "erreur";
    };
    if ($@) {
        print "erreur catch: $@\n"
    }
    Recherche staigiaire(s) motivé(s) sur projet perl/reseau a grande echelle. Me contacter par mp.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    427
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 427
    Points : 459
    Points
    459
    Par défaut
    juste en passant: les thread en perl (j'espere que tu parle de "use threads" et non de "use Thread", l'ancienne implementation de perl 5.5) sont encore assez instable et peu efficace au niveau de la gestion memoire.
    Suivant ce que tu a a faire, c'est parfois mieux de tout faire en une seule thread (avec des trucs genre POE ou Event) ou carrement en multiprocess (fork à l'ancienne, avec finalement une meilleure gestion memoire assurée par le copy on write de l'os) si tu n'est pas sous windows (sous windows forks est émulé par perl avec des thread de toute facon...)
    Recherche staigiaire(s) motivé(s) sur projet perl/reseau a grande echelle. Me contacter par mp.

  4. #4
    Membre habitué

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Points : 142
    Points
    142
    Par défaut
    yop, merci pour ta réponse.
    - je connais pas 'croak', j'vais aller look ça.
    dans FTP.pm il n'y a pas /[die|croak] Timeout/ mais des appels vers Socket::INET et autre. est ce que le pb peut remonter à un autre module sans que j'en soit averti par le message d'erreur ?

    - est il possible de catcher une erreur qui vient d'un objet utilisé ? par ex en le protégeant à chaque fois qu'on l'utilise ?
    avec la methode eval{}; je ne pense pas que l'on puisse avoir un $@ au niveau "au dessus".. je suis peut être très clair, j'espère vous voyez ce que je veux dire

    - j'ai réussi à trouvé un ptit topo pas mal mais incomplet à mon gout (cf ici)
    la méthode eval{};if($@){} semble un peu dépassée et à remplacer par ça :
    use Error qw(:try);
    use Fatal qw(open);

    my $file='none';
    try {
    open(FH,$file);
    my $lol=<FH>;
    }
    catch Error with {
    print "$file n'existe pas...\n";
    }
    finally{
    print "J'suis dans finally :p\n";
    };
    print "Je fini normalement ^^\n";
    exit 0;
    la methode throw est aussi accessible pour lever des exeptions au lieu de retourner des message d'erreurs. Vivement les new versions avec que des levage d'exeption partout !!!

    bon si kelk1 a des réponses ou plus d'infos je suis preneur
    ++

  5. #5
    Membre habitué

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Points : 142
    Points
    142
    Par défaut
    pour les threads, j'utilise ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    use Config; # le module Thread est il compilé ?
    $Config{useithreads} or die "Recompilez Perl avec les threads activés pour faire tourner ce programme.";     
    use threads; # Utilisation des threads
    use threads::shared; # Partager une variable avec les autres threads
    use Thread::Queue; # FIFO (nickel pour répartir le boulot entre les threads)
    use Thread::Semaphore; # pour locker une resource ;)

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    427
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 427
    Points : 459
    Points
    459
    Par défaut
    pour ta premiere question, oui c'est le read qui fait un die

    le coup du eval/test est la methode classique de gestion des exeptions en perl, mais effectivement elle n'est pas idéal puisqu'elle te retourne un string et non un objet d'erreur.
    Le module Error est idéal pour ce que tu veux faire effectivement.
    Par contre Fata c'est un peu autre chose: c'est un pragam (enfin une sorte de pragma...) qui force certaines fonctions syteme à faire un die (==exeption) au lieu de simplement renvoier false en cas d'erreur.
    En clair si tu fais un use Fatal 'open', tu n'as pas plus à tester la valeur de retour des open, et un simple open devient equivalent à un open || die;
    Recherche staigiaire(s) motivé(s) sur projet perl/reseau a grande echelle. Me contacter par mp.

  7. #7
    Membre habitué

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Points : 142
    Points
    142
    Par défaut
    merci pour toute tes infos pospos
    c'est quoi exactement un pragma ? un rapport avec le pragma no-cache des méta html ?
    Je viens de résoudre ma question principale à savoir peut on lever une exeption dans un script quand l'erreur provient d'une erreur "systeme" (par exemple un read ou pire un sysread) et qu'elle n'est pas dans le script même mais dans l'instance d'un objet que l'on utilise ? à priori j'aurai dit non puisque l'erreur qui se produit ne vient même pas d'un die mais la réponse est OUI !!! Vive Perl !!!
    De même, si on a un die qui se produit dans un objet, on peut l'empêcher de mettre fin au script en catchant toute action sur l'objet !!!
    c'est de la bombe de balle !!! perl est vraiment un langage génial !!! il n'a pas vraiment pas grand chose à envier aux langages objets ou non de plus bas niveau si ce n'est de ne pas avoir besoin de gérer les allocations et les controles de types !

    Voici les tests que j'ai fait avec quelques commentaires :

    1. une classe objet avec une methode impliquant un die et une autre impliquant une erreur systeme :
    pour le télécharger, c'est ici
    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
    52
    53
    54
    55
    56
     
    #!C:\Perl\bin
    use strict;
    package errorGenerator;
     
    #constructeur
    sub new {
        # la fct reçoit comme 1er param le nom d'la classe
        my ($classe,$param1,$param2) = @_;
     
        # référence vers une table de hachage des attributs
        my $this = {param1=>'no value', param2=>'no value'};
        $this->{param1}=$param1 if (defined($param1));
        $this->{param2}=$param2 if (defined($param2));
     
        # on lie la référence des attributs  à la classe
        bless ($this,$classe);
     
        # on retourne la référence consacrée aux attributs
        return $this; 
    }
     
     
    # Destructeur (invoquée à chaque fois que plus aucune référence ne pointera vers l'objet)
    # Rq : par ex, si une référence sur un objet est mise à undef, cette methode est appelée
    sub DESTROY {
        my ($this) = @_;
        print "[destructeur errorGenerator] L'objet va etre détruit !\n";
    }
     
     
    # une méthode n'est qu'une fonction recevant un premier paramètre un peu spécial :
    # la référence vers l'objet sur lequel elle doit s'appliquer
    sub params { 
        my ($this, $param1, $param2) = @_;    
        $this->{param1} = $param1 if (defined($param1));
        $this->{param2} = $param2 if (defined($param2));
        print "\t- param1 : $this->{param1}\n\t- param2 : $this->{param2}\n";
    }
     
    sub errorSystem{
        my $this=shift;
        my $file='lol';
        open(FH,$file);
        my $buf;
        my $len=sysread(FH,$buf,1024);
        print $buf;
    }
     
    sub errorDie{
        my $this=shift;
        my $file='lol';
        open(FH,$file)||die("[objet errorGenerator] Le fichier $file n'existe pas :s\n");
    }
     
    1; # indique la fin du module


    2. : Le script simpliste de Test :
    pour le télécharger, c'est ici

    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
     
    #!C:\Perl\bin
    use strict;
    use errorGenerator;
    use Error qw(:try);
    use Fatal qw(open);
     
    my $error=errorGenerator->new();
    print "1.: Test de l'affichage des params :p\n";
    $error->params('yo !!!');
     
     
    print "\n\n2.: Test de recuparation d'un Die ^_^\n";
    try {
        $error->errorDie();
    }
    catch Error with {
        print "\tJ'ai catch un Die !!! (use Error)\n";
    }
    finally{
        print "\tJ'suis dans finally :p (obligatoire sinon message d'erreur parasite...)\n";
    };
     
     
    print "\n\n3.: Test de recuparation d'une erreur System ^_^\n";
    try {
        $error->errorSystem();
    }
    catch Error with {
        print "\tJ'ai catch une erreur systeme !!! (use Error;use Fatal;)\n";
    }
    finally{
        print "\tJ'suis dans finally :p (obligatoire sinon message d'erreur parasite...)\n";
    };
     
     
    print "\n\n4.: J'ai bien fini a la fin du script sans aucune erreur !!! ^_^\n\n";
    exit 0;

    3. : Le résultat de l'éxécution du script sous ActivePerl-5.8.8.817-MSWin32-x86-257965




    4. : Les observations !!!

    - Finally est obligatoire si on ne veut pas avoir un message parasite à la fin du script (tout se déroule normal mais petit message...)
    Rq : pas grave, au pire on le met vide

    - use Fatal n'est pas nécessaire même pour lever une erreur systeme.
    Dans le cas de l'erreur systeme le code du catch n'est pas exécuté. En revanche l'erreur est levée et au lieu de stopper l'exécution, le code dans le finally est exécuté !

    Voilà !
    ça l'fait grave, j'vais pouvoir me remettre à mon taff demain et faire un script ultra robuste implantable !!!

    N'JoY !

    J'espère que tout ceci servira à d'autres
    Si vous voulez, je peux en faire une version un peu mieux pour l'intégrer dans la FAQ
    ++

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    427
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 427
    Points : 459
    Points
    459
    Par défaut
    j'ai pas lu tout ton post (désolé, je le lirais demain, ca a l'air interessant), mais pour le coup du pragma:
    en perl on appel pragma un module qui a une action particuliere, genre modification du comportement global (au lieu de simplement exporter des fonction ou implementer une classe).
    Donc par exemple comme pragma connus tu a strict, warnings, lib ou base, et Fatal devrait en etre un aussi. Mais ca n'en est pas un pour la simple et bonne raison qu'il commence par une majuscule. Ca ne change rien au code ou a la facon dont perl l'interprete mais c'est simplement une convention: les pragmas sont en minuscules et les modules en majuscule.
    Donc par exemple ton module errorGenerator devrait s'appeler ErrorGenerator.
    Recherche staigiaire(s) motivé(s) sur projet perl/reseau a grande echelle. Me contacter par mp.

  9. #9
    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
    Citation Envoyé par ramislebob
    - use Fatal n'est pas nécessaire même pour lever une erreur systeme.
    Dans le cas de l'erreur systeme le code du catch n'est pas exécuté. En revanche l'erreur est levée et au lieu de stopper l'exécution, le code dans le finally est exécuté !
    Tu as remarqué qu'il n'y a pas que le catch pour ratrapper les erreurs ? Et que justement otherwise est là pour ratrapper les exceptions qui ne sont pas traitées par une clause catch (ou une clause except) ?

    --
    Jedaï

  10. #10
    Membre habitué

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Points : 142
    Points
    142
    Par défaut
    yep ^^
    c'est vrai que j'en ai pas parlé mais bon, pas trop la peine de les test pour mon pb...

    La syntaxe complète est la 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
     
    try{
    # Ici le code susceptible de lever une exception
    }
    catch Error with{
    # On tente de catcher l'exception
    # PS : au lieu d'avoir une exception Error générale, on peut être plus spécifique (par ex Error::IO) et bien sur traiter différemment les types d'exception.
    # Rq : l'ordre des catch est alors important ;)
    }
    except{
    # dans le cas de Handler.
    # pas trop compris ce que ça fait pour l'instant :s
    }
    otherwise{
    # Récupère toutes les exceptions non catchée
    }
    finally{
    # Code executé dans tous les cas (exception catchée ou non)
    };
    PS : merci pospos pour la def du pragma
    Rq : pour les noms de classe je suis trop habitué aux conventions Java mais j'essaierai de m'en souvenir :p
    ++

  11. #11
    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
    Citation Envoyé par ramislebob
    Rq : pour les noms de classe je suis trop habitué aux conventions Java mais j'essaierai de m'en souvenir :p
    ++
    Selon les convention Java, tous les noms de classe doivent commencer par une majuscule, elles sont donc en accord avec les conventions de nommage des modules (pseudo-classes) en Perl.

    --
    Jedaï

  12. #12
    Membre habitué

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Points : 142
    Points
    142
    Par défaut
    arf... il me semblait pas... :s
    pourtant j'en ai refait pas mal cette année à l'école
    j'ai du devenir trop vite feignant et vouloir éviter d'appuyer sur MAJ ds mon shell pour lancer mes progs :s

  13. #13
    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
    Citation Envoyé par ramislebob
    arf... il me semblait pas... :s
    pourtant j'en ai refait pas mal cette année à l'école
    j'ai du devenir trop vite feignant et vouloir éviter d'appuyer sur MAJ ds mon shell pour lancer mes progs :s
    Ce sont les noms des variables locales, des variables d'instances et de méthode qui commencent par une minuscule et continuent en CamelCase. Les noms de classes commencent par une majuscule (par exemple : System, Math, Integer, Array, Class....).

    --
    Jedaï

  14. #14
    Membre habitué

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Points : 142
    Points
    142
    Par défaut
    Citation Envoyé par Jedai
    Ce sont les noms des variables locales, des variables d'instances et de méthode qui commencent par une minuscule et continuent en CamelCase. Les noms de classes commencent par une majuscule (par exemple : System, Math, Integer, Array, Class....).

    --
    Jedaï
    ça me revient maintenant :p
    merci pour ces précisions

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. gestion des exceptions via <error-page>
    Par mrjeronimo dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 16/08/2010, 13h26
  2. [ORACLE 9i] Gestion des exceptions
    Par sygale dans le forum SQL
    Réponses: 6
    Dernier message: 19/08/2004, 15h06
  3. Gestion des exception (EOleException)
    Par shurized dans le forum Bases de données
    Réponses: 5
    Dernier message: 30/06/2004, 17h25
  4. [XMLRAD] gestion des exceptions
    Par pram dans le forum XMLRAD
    Réponses: 2
    Dernier message: 28/01/2003, 17h48
  5. c: gestion des exceptions
    Par vince_lille dans le forum C
    Réponses: 7
    Dernier message: 05/06/2002, 14h11

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