2010-05-19 3 views
14

j'apprends Perl, et dans un grand nombre des exemples que je vois des erreurs sont traitées comme celui-ciQuelles sont les meilleures pratiques pour la gestion des erreurs dans Perl?

open FILE, "file.txt" or die $!; 

est-die au milieu d'un script vraiment la meilleure façon de traiter une erreur?

+6

Pour les discussions sur les exceptions perl, voir [Qu'est-ce qui est cassé à propos des exceptions en perl?] (Http://stackoverflow.com/questions/2165161/whats-broken-about-exceptions-in-perl), [utilisez-vous un classe d'exception dans vos programmes Perl? Pourquoi ou pourquoi pas?] (Http://stackoverflow.com/questions/2439966/do-you-use-an-exception-class-in-your-perl-programs-why-or-why-not), et [ Gestion des exceptions orientées objet en Perl - cela en vaut-il la peine?] (Http://stackoverflow.com/questions/503189/object-oriented-exception-handling-in-perl-is-it-worth-it) – Ether

Répondre

21

Siest approprié au milieu du script dépend vraiment de ce que vous faites. Si ce n'est que des dizaines de lignes, alors ça va. Un petit outil avec quelques centaines de lignes, puis envisager d'avouer (voir ci-dessous). Si c'est un grand système orienté objet avec beaucoup de classes et de code interconnecté, alors un objet d'exception serait peut-être mieux.

confessons dans le paquet Carp:
Souvent, le bug qui a conduit à la filière n'est pas sur la ligne qui meurent des rapports. Remplacer le dé avec avouer (voir paquet Carp) donnera la trace de la pile (comment nous sommes arrivés à cette ligne) qui facilite grandement le débogage.

Pour la gestion des exceptions à partir de builtins Perl, j'aime utiliser autodie. Il attrape les échecs de open et d'autres appels système et lance des exceptions pour vous, sans avoir à faire le bit or die. Ces exceptions peuvent être capturées avec un , ou mieux encore, en utilisant Try::Tiny.

+4

+1 pour suggérer «autodie». –

+1

J'ai toujours pensé qu'ils devraient l'appeler 'autoOrDie' :) – friedo

+0

@friedo Cela ressemblerait beaucoup à' authorDie' :) – dolmen

3

L'approche la plus moderne consiste à utiliser la bibliothèque standard Carp.

use Carp; 
my $fh; 
open $fh, '<', "file.txt" or confess($!); 

Le principal avantage est de donner une trace de pile à la mort.

+0

Well , croak ne donne pas une trace de pile à moins de définir d'autres objets de Carp. –

+0

@brian: whoop, corrigé. –

+1

Merci! Je ne savais pas à propos des carpes ... mais depuis quand les carpes croassent-elles? – SystematicFrank

0

J'utilise mourir, mais je l'envelopper dans des blocs eval pour le contrôle de la gestion des erreurs:

my $status = eval 
{ 
    # Some code... 
}; 

Si le 'eval' échoue:

  1. $status sera indéfini.
  2. [email protected] sera réglé sur ce que le message d'erreur a été produit (ou le contenu de un die)

Si le 'eval' réussit:

  1. $status sera la dernière valeur renvoyée de la bloc.
  2. [email protected] sera défini sur ''.
+5

Il y a une tonne de problèmes avec 'eval {}' qui nécessitent des contournements obscurs. Utilisez Try :: Tiny à la place. Il enveloppe toute la plaque réfrigérée dans un emballage propre et facile à utiliser. – daotoad

+1

Il y a une tonne de problèmes avec 'eval {}' qui nécessitent des contournements obscurs ... si vous vous souciez d'identifier l'erreur. Si vous voulez effectuer la même action indépendamment de sa cause, un simple bloc 'eval' fonctionne correctement. Mais, ouais: Utilisez Try :: Tiny dans tous les autres cas. –

+0

Je vais essayer ça la prochaine fois que j'écrirai du Perl. J'utilise cette façon de simuler un try-catch (en ajoutant une vérification de $ @ après le bloc eval.) Merci pour les conseils. –

12

Depuis que j'utilise Log::Log4perl presque partout, j'utilise $logger->logdie au lieu de die. Et si vous voulez avoir plus de contrôle sur vos exceptions, pensez à Exception::Class.

Il est préférable d'attraper vos exceptions avec Try::Tiny (voir sa documentation pourquoi).

6

Sauf si vous avez une idée plus précise, alors oui vous voulez mourir quand des choses inattendues se produisent.

  • Mourir à l'échec d'ouvrir un fichier et de donner le nom du fichier est mieux que le système vous dire qu'il ne peut pas lire ou écrire à un anonyme non défini.

  • Si vous parlez d'un "script", en général, vous parlez d'un simple morceau de code. Pas de couches qui ont besoin de coordination (pas habituellement). Dans un Perl Module, il y a une idée auxiliaire qui est que vous ne possédez pas l'environnement d'exécution, donc le logiciel principal se soucie et il attrape les choses dans un eval, OU il ne s'en soucie pas vraiment et mourir serait bien. Cependant, il faut essayer un peu plus de robustesse en tant que module et simplement retourner undefs ou quelque chose.

  • Vous pouvez attraper n'importe quelles matrices (ou croassements) dans un bloc d'évaluation. Et vous pouvez faire votre manipulation plus spécifique là-bas. Mais si vous voulez inspecter $! puis écrivez ce code, et vous aurez une résolution plus spécifique. Consultez la norme quasi-universelle d'utilisation strict. C'est un code qui meurt sur une syntaxe discutable, plutôt que de vous laisser continuer.

Je pense donc que l'idée générale est: oui , DIE sauf si vous avez une meilleure idée de la façon dont les choses doivent être traitées. Si vous y mettez suffisamment de prévoyance, vous pouvez être pardonné pour la ou les deux fois où vous ne mourrez pas, parce que vous n'avez pas besoin de le faire.

Questions connexes