web-dev-qa-db-fra.com

Comment utiliser correctement le catch catch en Perl fourni par error.pm?

J'ai trouvé qu'il y a le module Error qui fournit des fonctionnalités d'essai et de capture comme en Java. Mais je ne sais pas comment imprimer l'exception qui revient.

Je voudrais comprendre comment faire ce qui suit

try {
    // do something that will fail!

} catch (Error e) {
    // Print out the exception that occurred
    System.out.println(e.getMessage());
}

Comment obtenir l'impression de l'erreur avec la trace de pile?

32
pitchblack408

Vous feriez probablement mieux d'utiliser Try :: Tiny qui vous aidera à éviter un certain nombre de pièges avec les anciens Perls .

use Try::Tiny;

try {
        die "foo";
} catch {
        warn "caught error: $_";
};
53
Sinan Ünür

La dernière fois que j'ai vérifié, Erreur était obsolète. Mais voici comment vous le feriez sans ce module:

eval {
    die "Oops!";
    1;
} or do {
    my $e = $@;
    print("Something went wrong: $e\n");
};

Fondamentalement, utilisez eval au lieu de try, die au lieu de throw, et recherchez l'exception dans $@ . La vraie valeur à la fin du bloc eval fait partie d'un idiome pour empêcher $@ de changer involontairement avant d'être réutilisé dans les versions Perl antérieures à 5.14, voir P :: C :: P :: ErrorHandling :: RequireCheckingReturnValueOfEval pour plus de détails. Par exemple, ce code souffre de cette faille.

# BAD, DO NOT USE WITH PERLS OLDER THAN 5.14
eval {
    die "Oops!";
};
if (my $e = $@) {
    print("Something went wrong: $e\n");
}
# BAD, DO NOT USE WITH PERLS OLDER THAN 5.14

Mais notez que de nombreuses opérations Perl ne déclenchent pas d'exceptions lorsqu'elles échouent; ils renvoient simplement un code d'erreur. Ce comportement peut être modifié via autodie pour les modules internes et standard. Si vous utilisez autodie, alors la façon standard de faire try/catch est la suivante (directement à partir du perldoc autodie):

use feature qw(switch);

eval {
   use autodie;

   open(my $fh, '<', $some_file);

   my @records = <$fh>;

   # Do things with @records...

   close($fh);

};

given ($@) {
   when (undef)   { say "No error";                    }
   when ('open')  { say "Error from open";             }
   when (':io')   { say "Non-open, IO error.";         }
   when (':all')  { say "All other autodie errors."    }
   default        { say "Not an autodie error at all." }
}

Pour obtenir une trace de pile, regardez Carp .

45
Mark Reed

Si vous voulez quelque chose d'un peu plus puissant que Try :: Tiny, vous voudrez peut-être essayer de regarder le module TryCatch dans CPAN.