Ruby에서 예외를 포착 한 후 다시 발생 (동일한 예외)


84

예외를 포착하여 Ruby 기술을 향상 시키려고합니다. 여러 메서드 호출이있을 때 같은 종류의 예외를 다시 발생시키는 것이 일반적인지 알고 싶습니다. 그렇다면 다음 코드가 의미가 있습니까? 같은 종류의 예외를 다시 발생 시켜도 괜찮습니까, 아니면 프로세스 메서드에서 포착해서는 안됩니까?

class Logo
  def process
    begin
      @processed_logo = LogoProcessor::create_image(self.src)
    rescue CustomException
      raise CustomException
    end
  end
end

module LogoProcessor
  def self.create_image
    raise CustomException if some_condition
  end
end

답변:


168

때때로 우리는 실제로 오류를 처리 하지 않고도 오류가 발생 했음을 알고 싶어합니다 .

오류 처리를 담당하는 사람은 개체의 사용자 인 호출자 인 경우가 많습니다. 오류에 관심이 있지만 그 책임을 맡고 싶지 않다면 어떻게해야합니까? 오류를 구하고 필요한 모든 작업을 수행 한 다음 아무 일도 없었던 것처럼 신호를 스택 위로 전파합니다.

예를 들어 오류 메시지를 기록한 다음 호출자가 처리하도록하려면 어떻게해야합니까?

begin
  this_will_fail!
rescue Failure => error
  log.error error.message
  raise
end

raise인수없이 호출 하면 마지막 오류가 발생합니다. 우리의 경우, 우리는 error.

질문에 제시 한 예에서 오류를 다시 제기 할 필요는 없습니다. 자연스럽게 스택 위로 전파되도록 할 수 있습니다. 예제의 유일한 차이점은 마지막 오류 개체를 다시 발생시키는 대신 새 오류 개체를 만들고 발생시키는 것입니다.


흥미 롭군. 내 질문은 프로세스 정의에서 오류를 포착하지 못하면 프로세스 메서드 (예 :)를 호출 할 때 포착해야 begin @logo.process; rescue...하지만 프로세스 자체에서 시작된 예외를 포착하지 않을 것입니다. 하지만 프로세스 내에서 호출 된 것입니다. 그게 맞습니까?
Hommer Smith

2
이것은 stacktrace원래 예외에서 cause
풀릴

4
raise이 답변 방식의 @bjhaid 호출 은 backtrace. cause이 경우에는 적용되지 않습니다. 오히려 rescue블록이 새 예외를 발생 시키면 자동으로 채워집니다 .
담당자 :

@HommerSmith : raise (이 경우에는 log.error이지만 어떤 것이 든 될 수 있음) 전 줄이 실패하면 어떻게됩니까? 나는 그것을 "확보"하려고 생각하고 있지만, 확실히 내에서 "raise"의 인수로 오류에 대한 참조를 사용해야합니다. 그것에 대해 어떻게 생각하십니까?
jgomo3

1
@ RafałCieślak 오류가 발생할 때마다 $!전역 변수에 할당됩니다 . 호출 raise인수없이하는 것은에 포함 된 오류가 발생합니다 $!효과적으로 마지막 오류 인상을. 그러나 raise error는에 포함 된 error동일한 객체 일 수도 있고 아닐 수도 있는 지역 변수에 포함 된 오류를 발생시킵니다 $!. 내 예에서 $!와 동일합니다 error. 그러나,이 작업을 수행 할 수도 있습니다 :error = Exception.new; raise error
마테우스 모레이라

3

이렇게하면 원본과 동일한 유형의 오류가 발생하지만 메시지를 사용자 지정할 수 있습니다.

rescue StandardError => e
  raise e.class, "Message: #{e.message}"

이것은 모든 종류의 저수준 함수를 포함하고 프로그램을 중단시킬 수 있기 때문에 StandardError를 잡는 것은 나쁜 생각입니다.
Paul Whitehead

1
우리는 즉시 예외를 다시 제기하기 때문에 이것이 규칙에 대한 "예외"라고 생각합니다.
FreePender
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.