English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Las excepciones y la ejecución siempre están relacionadas. Si abre un archivo inexistente y no maneja adecuadamente esta situación, su programa se considera de baja calidad.
Si ocurre una excepción, el programa se detiene. Las excepciones se utilizan para manejar varios tipos de errores, que pueden ocurrir durante la ejecución del programa, por lo que se deben tomar medidas adecuadas para evitar que el programa se detenga completamente.
Ruby ofrece un mecanismo perfecto para manejar excepciones. Podemos comienzo/fin En el bloque se adjunta el código que puede lanzar excepciones, y se utiliza rescue La cláusula indica el tipo de excepción que Ruby debe manejar perfectamente.
begin #comienza raise.. #lanza una excepción rescue [ExceptionType = StandardException] #captura la excepción del tipo especificado, el valor predeterminado es StandardException $! #indica la información de la excepción $@ #indica la ubicación del código donde se produjo la excepción else #otras excepciones .. ensure # Ingresar al bloque de código sin importar si hay o no excepciones end # Finalizar
desde comienzo a rescue es protegido. Si se produce una excepción durante la ejecución del bloque de código, el control se transfiere a rescue lo que está en fin y
entre los bloques. comienzo para rescue cada
postcisos, Ruby compara la excepción lanzada con cada parámetro en turno. Si el tipo de excepción nombrado en el bloque 'rescue' coincide con el tipo de excepción actual o es una subclase de la excepción, se realiza una coincidencia exitosa. rescue Si la excepción no coincide con todos los tipos de errores especificados, podemos usar todos los else postciso.
#!/usr/bin/ruby comienzo file = open("/unexistant_file) if file puts "File opened successfully" fin rescue file = STDIN fin print file, "==", STDIN, "\n"
El resultado de ejecutar el ejemplo anterior es. Puedes ver que,STDIN reemplazó file porqueal abrirfalló.
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
Puedes usar rescue El bloque captura la excepción y luego usa retry La sentencia comienza a ejecutarse desde el principio comienzo bloque.
comienzo # La excepción lanzada por este código se capturará por el siguiente bloque 'rescue' rescue # Este bloque capturará todos los tipos de excepciones retry # Esto llevará el control al inicio de 'begin' fin
#!/usr/bin/ruby comienzo file = open("/unexistant_file) if file puts "File opened successfully" fin rescue fname = "existant_file" retry fin
A continuación, se muestra el flujo de procesamiento:
Se produjo una excepción al abrir.
Salta a 'rescue'. 'fname' se reasigna.
Salta al inicio de 'begin' usando 'retry'.
Esta vez se abrió el archivo con éxito.
Continúa con el proceso básico.
Atención:Si el archivo renombrado no existe, el código de ejemplo en este ejemplo intentará infinitamente. Por lo tanto, usa con cautela la gestión de excepciones. retry.
Puedes usar raise La sentencia lanza una excepción. El siguiente método lanza una excepción en el momento de la llamada. Su segundo mensaje se mostrará.
raise o raise "Error Message" o raise ExceptionType, "Error Message" o raise ExceptionType, "Error Message" condition
La primera forma simplemente relanza la excepción actual (si no hay excepción actual, lanza un RuntimeError). Esto se utiliza en el administrador de excepciones que necesita explicar la excepción antes de pasarla.
La segunda forma crea una nueva RuntimeError Excepción, configura su mensaje con la cadena proporcionada. La excepción se lanza después de la pila de llamadas.
La tercera forma utiliza el primer parámetro para crear una excepción y luego configura el mensaje relevante como el segundo parámetro.
La cuarta forma es similar a la tercera, puede agregar cualquier condición adicional (por ejemplo}} unless)para lanzar una excepción.
#!/usr/bin/ruby comienzo puts 'Estoy antes del raise.' raise 'Se ha producido un error.' puts 'Estoy después del raise.' rescue puts 'Estoy siendo rescate.' fin puts 'Estoy después del bloque begin.'
El resultado de salida del ejemplo anterior es:
Estoy antes del raise. Estoy siendo rescate. Estoy después del bloque begin.
Otro ejemplo raise Ejemplo de uso:
#!/usr/bin/ruby comienzo raise 'Una excepción de prueba.' rescue Exception => e puts e.message puts e.backtrace.inspect fin
El resultado de salida del ejemplo anterior es:
Una excepción de prueba. ["main.rb:4"]
A veces, independientemente de si se lanza una excepción o no, es necesario garantizar que ciertos procesos se completen al finalizar el bloque de código. Por ejemplo, puede que abra un archivo al ingresar al bloque y necesite asegurarse de cerrarlo al salir del bloque.
asegurar Lo que hace la cláusula es esto. La cláusula ensure se coloca después del último rescate y contiene un bloque de código que siempre se ejecuta al finalizar el bloque. No importa si el bloque sale normalmente, si lanza y maneja una excepción, o si termina debido a una excepción no capturada,asegurar El bloque siempre se ejecuta.
comienzo #.. Proceso #.. Lanza excepción rescue #.. Maneja errores asegurar #.. Asegura que se ejecute finalmente #.. Esto siempre se ejecuta fin
comienzo raise 'Una excepción de prueba.' rescue Exception => e puts e.message puts e.backtrace.inspect asegurar puts "Asegurando ejecución" fin
El resultado de salida del ejemplo anterior es:
Una excepción de prueba. ["main.rb:4"] Asegurando ejecución
si se proporciona else cláusula, que generalmente se coloca en rescue Después de la cláusula, cualquier asegurar Antes.
else La parte principal de la cláusula solo se ejecuta cuando el cuerpo del código no lanza una excepción.
comienzo #.. Proceso #.. Lanza excepción rescue #.. Maneja errores else #.. Si no hay excepciones, ejecuta asegurar #.. Asegura que se ejecute finalmente #.. Esto siempre se ejecuta fin
comienzo # Lanza una 'excepción de prueba'. puts "No estoy lanzando una excepción" rescue Exception => e puts e.message puts e.backtrace.inspect else puts "¡Felicidades"-- ¡sin errores!" asegurar puts "Asegurando ejecución" fin
El resultado de salida del ejemplo anterior es:
No estoy lanzando una excepción ¡Felicidades!-- ¡sin errores! Asegurando ejecución
Se puede capturar el mensaje de error lanzado utilizando la variable $!
El mecanismo de excepciones raise y rescue puede abandonar la ejecución en caso de error, a veces es necesario saltar algunas estructuras de anidación profunda en el procesamiento normal. En estos casos, catch y throw son muy útiles.
catch Se define un bloque que utiliza un nombre dado (puede ser un Symbol o String) como etiqueta. El bloque se ejecutará normalmente hasta que se encuentre un throw.
throw :lablename #.. Esto no se ejecutará catch :lablename do #.. Se ejecutará después de encontrar un throw fin o throw :lablename condition #.. Esto no se ejecutará catch :lablename do #.. Se ejecutará después de encontrar un throw fin
En el siguiente ejemplo, si el usuario ingresa '!' como respuesta a cualquier solicitud, se utiliza un throw para finalizar la interacción con el usuario.
def promptAndGet(prompt) print prompt res = readline.chomp throw :quitRequested if res == "!" return res fin catch :quitRequested do nombre = promptAndGet("Nombre: ") edad = promptAndGet("Edad: ") sexo = promptAndGet("Sexo: ") # .. # Procesar información fin promptAndGet("Nombre:")
El programa anterior requiere interacción manual, puede probarlo en su computadora. Los resultados de ejecución de los ejemplos anteriores son los siguientes:
Nombre: Ruby on Rails Edad: 3 Sexo: ¡ Nombre: Just Ruby
Las clases y módulos estándar de Ruby lanzan excepciones. Todas las clases de excepción forman una jerarquía, incluyendo la clase Exception en la cima. La siguiente capa consta de siete tipos diferentes:
Interrupt
NoMemoryError
SignalException
ScriptError
StandardError
SystemExit
Fatal es otra excepción en esta capa, pero el intérprete de Ruby solo lo utiliza internamente.
ScriptError y StandardError tienen algunas subclases, pero aquí no necesitamos conocer estos detalles. Lo más importante es crear nuestra propia clase de excepción, que debe ser una subclase de Exception o de alguna de sus subclases.
Veamos un ejemplo:
class FileSaveError < StandardError attr_reader :reason def initialize(reason) @reason = reason fin fin
Ahora, veamos el siguiente ejemplo, que utiliza la excepción anterior:
File.open(path, "w") do |file| comienzo # Escribir datos ... rescue # Error producido raise FileSaveError.new($!) fin fin
En este caso, la línea más importante es raise FileSaveError.new($!)Llamamos a raise para indicar que se ha producido una excepción, y se la pasamos a un nuevo ejemplo de FileSaveError, ya que el fallo de escritura de datos se debe a una excepción específica.