코드가 해당 예외의 수명 주기를 제어하지 않는 경우에도 가장 최근의 예외를 가져올 수 있는 것이 종종 유용합니다. 애플리케이션에 기본 충돌 감지를 추가하고 싶다고 상상해 보십시오. 포착되지 않은 예외의 결과로 발생하는 충돌에 대한 추가 정보를 기록하고 싶습니다.
첫 번째 단계는 애플리케이션이 종료될 때마다 실행되는 핸들러를 추가하는 것입니다. Ruby 커널의 at_exit 메소드를 통해 이 작업을 수행하는 것은 매우 쉽습니다.
at_exit
puts "the app exited"
end
그러나 예외의 결과로 종료 콜백이 호출되었는지 어떻게 알 수 있습니까? 음, Ruby는 암호로 명명된 $!
를 제공합니다. 전역 변수. 현재 호출 스택의 어딘가에서 발생한 가장 최근에 발생한 예외를 포함합니다.
$!
를 사용하는 것은 간단합니다. 예외로 인해 프로그램이 종료되고 있는지 감지합니다. 다음과 같이 보입니다.
at_exit do
save_error_to_log($!) if $!
end
$!
의 한계
유감스럽게도 $!
메서드는 현재 호출 스택의 어딘가에서 예외가 발생한 경우에만 작동합니다. 예외를 구한 경우 $!
에 액세스하십시오. 구제 조항을 벗어나면 nil이 됩니다.
begin
raise "x"
rescue
puts $! # => RuntimeError
end
puts $! # => nil
즉, $!
IRB와 같은 쉘 내부에서는 거의 쓸모가 없습니다. 종종 IRB에서 메서드를 실행하고 예외를 얻습니다. 때때로 나는 그 예외 객체를 잡고 싶습니다. 하지만 $!
작동하지 않습니다.
irb(main):001:0> 1/0
ZeroDivisionError: divided by 0
from (irb):1:in `/'
irb(main):002:0> $!
=> nil
$! PRY와 함께
PRY는 $!
의 한계를 극복합니다. 자체 로컬 변수 _ex_
를 추가하여 . 이 변수는 가장 최근에 포착되지 않은 예외를 포함합니다.
[1] pry(main)> raise "hi"
RuntimeError: hi
from (pry):1:in `__pry__'
[2] pry(main)> _ex_
=> #<RuntimeError: hi>
PRY가 이것을 할 수 있는 이유는 PRY 또는 IRB 내부에 실제로 포착되지 않은 예외가 없기 때문입니다. 쉘 자체가 예외를 포착하여 멋진 형식의 오류 메시지로 표시합니다.
아래 PRY 소스의 관련 비트를 복사했습니다. 명령을 평가하는 코드가 begin/rescue/end 블록 내부에 래핑된 것을 볼 수 있습니다. 복구 가능한 예외가 발생하면 PRY가 예외를 self.last_exception에 저장하고 나중에 _ex_
에 할당됩니다. .
# Excerpted from the PRY source at https://github.com/pry/pry/blob/623306966bfa86890ac182bc8375ec9699abe90d/lib/pry/pry_instance.rb#L273
begin
if !process_command_safely(line)
@eval_string << "#{line.chomp}\n" if !line.empty? || !@eval_string.empty?
end
rescue RescuableException => e
self.last_exception = e
result = e
Pry.critical_section do
show_result(result)
end
return
end
영어 필요
$!
와 같은 변수 이름을 찾을 수 있습니다. 눈이 좀 힘든? 다행히 Ruby에는 로봇 낱말처럼 보이는 많은 전역 변수의 영어 버전을 제공하는 "영어"라는 모듈이 포함되어 있습니다.
$!
의 동의어 $ERROR_INFO
입니다. . 일반적으로 $!
를 사용하는 모든 곳에서 사용할 수 있습니다. .
require "English"
begin
raise "x"
rescue
puts $ERROR_INFO # => RuntimeError
end
그리고 대부분의 다른 영어에 해당하는 내용은 이 블로그 게시물의 주제와 아무 관련이 없지만 참고용으로 포함하겠습니다. 영어 변수는 왼쪽에 있습니다. 원본은 오른쪽에 있습니다.
$ERROR_INFO | $! |
$ERROR_POSITION | $@ |
$FS | $; |
$FIELD_SEPARATOR | $; |
$OFS | $, |
$OUTPUT_FIELD_SEPARATOR | $, |
$RS | $/ |
$INPUT_RECORD_SEPARATOR | $/ |
$ORS | $\ |
$OUTPUT_RECORD_SEPARATOR | $\ |
$INPUT_LINE_NUMBER | $. |
$NR | $. |
$LAST_READ_LINE | $_ |
$DEFAULT_OUTPUT | $> |
$DEFAULT_INPUT | $< |
$PID | $$ |
$PROCESS_ID | $$ |
$CHILD_STATUS | $? |
$LAST_MATCH_INFO | $~ |
$IGNORECASE | $= |
$ARGV | $* |
$MATCH | $& |
$PREMATCH | $` |
$POSTMATCH | $' |
$LAST_PAREN_MATCH | $+ |