Exception rubis


Les exceptions et l'exécution sont toujours liées. Si vous ouvrez un fichier qui n'existe pas et ne gérez pas la situation de manière appropriée, votre programme est considéré comme de mauvaise qualité.

Si une exception se produit, le programme s'arrête. Les exceptions sont utilisées pour gérer différents types d'erreurs pouvant survenir lors de l'exécution du programme, afin que les mesures appropriées soient prises sans arrêter complètement le programme.

Ruby fournit un mécanisme parfait pour gérer les exceptions. Nous pouvons enfermer le code qui peut lever une exception dans un bloc begin/end et utiliser la clause rescue pour indiquer à Ruby quel type d'exception gérer.

Syntaxe

begin #开始
 
 raise.. #抛出异常
 
rescue [ExceptionType = StandardException] #捕获指定类型的异常 缺省值是StandardException
 $! #表示异常信息
 $@ #表示异常出现的代码位置
else #其余异常
 ..
ensure #不管有没有异常,进入该代码块
 
end #结束

Tout, du début au sauvetage est protégé. Si une exception se produit lors de l'exécution d'un bloc de code, le contrôle est passé au bloc entre rescue et end.

Pour chaque clause rescue du bloc begin, Ruby compare l'exception levée avec chaque argument tour à tour. Si l'exception nommée dans la clause de sauvetage est du même type que l'exception actuellement levée ou est la classe parent de l'exception, la correspondance réussit.

Si l'exception ne correspond pas à tous les types d'erreurs spécifiés, nous pouvons utiliser une clause else après toutes les clauses rescue.

Exemple

#!/usr/bin/ruby

begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
      file = STDIN
end
print file, "==", STDIN, "\n"

Le résultat de sortie de l'exemple ci-dessus est. Vous pouvez voir que STDIN ​​​​remplace le fichier car ne parvient pas à ouvrir .

#<IO:0xb7d16f84>==#<IO:0xb7d16f84>

Utilisez l'instruction retry

Vous pouvez utiliser le bloc rescue pour intercepter l'exception, puis utiliser l'instruction retry pour démarrer exécution depuis le début du bloc begin.

Syntaxe

begin
    # 这段代码抛出的异常将被下面的 rescue 子句捕获
rescue
    # 这个块将捕获所有类型的异常
    retry  # 这将把控制移到 begin 的开头
end

Instance

#!/usr/bin/ruby

begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
   fname = "existant_file"
   retry
end

Voici le flux de traitement :

  • Une exception s'est produite lors de l'ouverture.

  • Sauter à la rescousse. fname est réaffecté.

  • Sauter au début du début en réessayant.

  • Cette fois, le fichier a été ouvert avec succès.

  • Continuez avec le processus de base.

Remarque : Si le fichier renommé n'existe pas, le code de cette force essaiera à l'infini. Par conséquent, utilisez retry avec prudence lors de la gestion des exceptions.

Utilisation de l'instruction raise

Vous pouvez utiliser l'instruction raise pour lever une exception. La méthode suivante lève une exception lorsqu'elle est appelée. Son deuxième message sera émis.

Syntaxe

raise 

或

raise "Error Message" 

或

raise ExceptionType, "Error Message"

或

raise ExceptionType, "Error Message" condition

Le premier formulaire renvoie simplement l'exception actuelle (ou une RuntimeError s'il n'y a pas d'exception actuelle). Ceci est utilisé dans les gestionnaires d'exceptions qui doivent interpréter l'exception avant de la transmettre.

Le deuxième formulaire crée une nouvelle exception RuntimeError, définissant son message sur la chaîne donnée. L'exception est ensuite générée dans la pile d'appels.

Le troisième formulaire crée une exception en utilisant le premier paramètre, puis définit le message associé comme deuxième paramètre.

Le quatrième formulaire est similaire au troisième formulaire, vous pouvez ajouter des instructions conditionnelles supplémentaires (telles que sauf si) pour lever une exception.

Instance

#!/usr/bin/ruby

begin  
    puts 'I am before the raise.'  
    raise 'An error has occurred.'  
    puts 'I am after the raise.'  
rescue  
    puts 'I am rescued.'  
end  
puts 'I am after the begin block.'

L'exemple ci-dessus d'exécution du résultat de sortie est :

I am before the raise.  
I am rescued.  
I am after the begin block.

Un autre exemple démontrant l'utilisation de raise :

#!/usr/bin/ruby

begin  
  raise 'A test exception.'  
rescue Exception => e  
  puts e.message  
  puts e.backtrace.inspect  
end

ci-dessus Le résultat de sortie de l'instance en cours d'exécution est :

A test exception.
["main.rb:4"]

Utilisez l'instruction ensure

Parfois, qu'une exception soit levée ou non, vous devez vous assurer que certains traitements est terminé à la fin du bloc de code. Par exemple, vous pouvez avoir un fichier ouvert lorsque vous entrez et lorsque vous quittez le bloc, vous devez vous assurer de fermer le fichier.

C'est exactement ce que fait la clause

assurer. assurer est placé après la dernière clause de sauvetage et contient un bloc de code qui est toujours exécuté à la fin du bloc. Peu importe que le bloc se termine correctement, qu'il lève et gère une exception ou qu'il se termine par une exception non interceptée, le bloc ensure sera toujours exécuté.

Syntaxe

begin 
   #.. 过程
   #.. 抛出异常
rescue 
   #.. 处理错误 
ensure 
   #.. 最后确保执行
   #.. 这总是会执行
end

Exemple

begin
  raise 'A test exception.'
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
ensure
  puts "Ensuring execution"
end

Le résultat de l'exemple ci-dessus est :

A test exception.
["main.rb:4"]
Ensuring execution

Utilisez l'instruction else

Si la clause else est fournie, elle est généralement placée après la clause rescue et avant tout ensure. Le corps de la clause

else n'est exécuté que si le corps du code ne lève pas d'exception.

Syntaxe

begin 
   #.. 过程 
   #.. 抛出异常
rescue 
   #.. 处理错误
else
   #.. 如果没有异常则执行
ensure 
   #.. 最后确保执行
   #.. 这总是会执行
end

Exemple

begin
 # 抛出 'A test exception.'
 puts "I'm not raising exception"
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
else
   puts "Congratulations-- no errors!"
ensure
  puts "Ensuring execution"
end

Le résultat de l'exemple ci-dessus est :

I'm not raising exception
Congratulations-- no errors!
Ensuring execution

Utilisez la variable $! Le mécanisme d'exception de

Catch and Throw

raise and Rescue peut abandonner l'exécution lorsqu'une erreur se produit. Parfois, il est nécessaire de sortir de certaines structures profondément imbriquées pendant le traitement normal. C’est là que attraper et lancer s’avère utile.

catch définit un bloc qui utilise le nom donné (qui peut être un symbole ou une chaîne) comme étiquette. Le bloc s'exécutera normalement jusqu'à ce qu'un lancer soit rencontré.

Syntaxe

throw :lablename
#.. 这不会被执行
catch :lablename do
#.. 在遇到一个 throw 后匹配将被执行的 catch
end

或

throw :lablename condition
#.. 这不会被执行
catch :lablename do
#.. 在遇到一个 throw 后匹配将被执行的 catch
end

Exemples

Dans l'exemple suivant, si l'utilisateur tape '!' en réponse à une invite, un lancer est utilisé pour mettre fin à l'interaction avec l'utilisateur .

def promptAndGet(prompt)
   print prompt
   res = readline.chomp
   throw :quitRequested if res == "!"
   return res
end

catch :quitRequested do
   name = promptAndGet("Name: ")
   age = promptAndGet("Age: ")
   sex = promptAndGet("Sex: ")
   # ..
   # 处理信息
end
promptAndGet("Name:")

Le programme ci-dessus nécessite une interaction humaine, vous pouvez l'essayer sur votre ordinateur. Le résultat de sortie de l'exemple ci-dessus est :

Name: Ruby on Rails
Age: 3
Sex: !
Name:Just Ruby

Class Exception

Les classes et modules standard de Ruby lèvent des exceptions. Toutes les classes d'exception forment une hiérarchie, y compris la classe Exception en haut. Le niveau suivant comprend sept types différents :

  • Interrupt

  • NoMemoryError

  • SignalException

  • ScriptError

  • StandardError

  • SystemExit

Fatal est une autre exception dans cette couche, mais l'interpréteur Ruby ne l'utilise qu'en interne.

ScriptError et StandardError ont toutes deux des sous-classes, mais nous n'avons pas besoin de connaître ces détails ici. Le plus important est de créer nos propres classes d'exception, elles doivent être des sous-classes de la classe Exception ou de ses descendants.

Voyons un exemple :

class FileSaveError < StandardError
   attr_reader :reason
   def initialize(reason)
      @reason = reason
   end
end

Maintenant, regardez l'exemple suivant où l'exception ci-dessus sera utilisée :

File.open(path, "w") do |file|
begin
    # 写出数据 ...
rescue
    # 发生错误
    raise FileSaveError.new($!)
end
end

Ici, la ligne la plus importante est raise FileSaveError.new($!). Nous appelons raise pour indiquer qu'une exception s'est produite, en la transmettant à une nouvelle instance de FileSaveError qui n'a pas réussi à écrire des données en raison de l'exception spécifique.