Lovetoken

저는 개발 취향을 가진 데이터 분석가 Jr. 입니다.

Navigation
 » Home
 » About Me
 » Github

R에서 try(), tryCatch() 함수 소개

11 Feb 2016 » R



이전에 나는 특정 코드들이 있을 때, 이 코드를 수행하면 에러가 나는지, 나지 않는지 여부를 boolean 값으로 반환하는 그러한 함수를 찾고 있었다. (그보단 이러한 함수를 만들 수 있도록 리소스를 찾아보고 있었다)
그러던 중 우연히 알게 된 try() 함수에 대해 알아보고자 한다.

R이 처음으로 실행된 상황에서 (깔끔한 상태에서) 아래 코드는 bsid 라는 객체가 어떠한 환경에서도 없기 때문에 에러를 발생한다.
만약 .rmd 포맷으로 코딩을 하고 있는 상황이라면 오류나는 코드청크가 하나라도 있는 경우 랜더링이 막히게 될 것이다.
우선 랜더링마저 막히는 상황을 피하기 위해 코드청크의 옵션을 eval=F 로 설정했다.

bsid

실제로 위 코드를 실행시키면

> bsid
Error: object 'bsid' not found

의 에러메세지가 출력된다.



try() 함수

에러를 뿜는 위의 코드를 try() 함수로 감싸주어 보자.
감싼 이 코드는 단순히 “try” 라는 단어 대로 시도를 해보고 안되면 마는 식으로 동작하게 된다.

try(expr=bsid)

try() 함수 안에는 표현식(expr)이 들어가는데 여기에 bsid 를 입력하였다.
이 코드는 역시 에러가 반환된다. 하지만

bsid

이것과의 차이점은 에러를 반환하고도 이후 코드를 계속적으로 수행한다는 차이점을 가지고 있다.
무슨소리인지 잘 모르겠다면 아래코드를 보면 된다.

try(expr=bsid)

print("Hello R")
## [1] "Hello R"

try() 함수를 쓴 코드 이후의 코드인 print("Hello R") 은 정상적으로 실행되 수행된 것을 볼 수 있다.
유의할 것은 실제로 위 코드청크에 eval=F 설정을 주지 않고도 렌더링이 막히지 않았는다는 것이다.
따라서 에러를 뿜는 코드이더라 하더라도, 그것이 try() 함수로 감싸지면 계속적으로 수행된다는 것이다.


silent 인자

try() 함수의 silent 인자로 command 에 에러가 반환되는 메세지 조차 침묵시킬 수 있다.
이 인자의 값을 TRUE 로 설정하면 에러는 silent 시킨다.

try(bsid, silent = T)

차이점을 체감하기 위해선 직접 R 을 켜 코드를 동작시켜 볼 필요가 있다.


두 줄 의 코드를 try 하되 한줄은 정상, 한줄은 에러를 내는 코드로 수정하면?

try({
  print("Hello R")  # normal code
  bsid  # error code
}, silent = T)
## [1] "Hello R"

첫번째 코드는 정상적으로 문자열 “Hello R” 을 출력시킨다.
그리고 에러를 반환하는 2번째 코드는 반응이 없다.

순서를 바꾸어 보면?

try({
  bsid  # error code
  print("Hello R")  # normal code
}, silent = T)

흠 첫번째 코드가 에러를 뿜기 때문에 그 이후 코드인 print("Hello R")는 수행되지 않는것을 볼 수 있다. try() 함수에 감싸져있는 코드덩어리는 평소대로 에러코드 이후인 정상적 코드를 실행하지 못한다.



에러가 날 경우의 예외처리를 위한 tryCatch() 함수

이처럼 try() 함수를 알아 보았는데 잘 이용하면 에러가 나는 코드를 건너뛰고 다음 프로세스를 진행할 수 있다.
에러가 나는 상황에 대한 조건부 프로세스가 따로 필요하다면 try() 함수만으론 부족할 수 있다.
이럴때는 lowerCamelCase 로 네이밍된 tryCatch() 함수를 이용하면 간편하게 해결할 수 있다.

tryCatch(bsid,
  error = function(e) print("I am error"),
  warning = function(w) print("I am warning"),
  finally = NULL)
## [1] "I am error"

tryCatch() 에는 본코드가 에러를 뿜을 때 실행될 함수를 설정하는 error,
에러가 아니라 warning 가 일어날 때 실행될 함수를 설정하는 warning,
조건 상관없이 공통으로 실행되는 finally 인자들을 이용할 수 있어 좀 더 섬세한 예외처리가 가능하다.

위의 예제는 bsid 객체가 존재하지 않아 error 에 해당되는 print("I am error") 가 실행된 경우이다. 만약

bsid <- "I exist!"

를 실행한 다음 위의 코드를 실행한다면?

tryCatch(bsid,
  error = function(e) print("I am error"),
  warning = function(w) print("I am warning"),
  finally = NULL)
## [1] "I exist!"
“그래 넌 존재해” 라는 결론을 낼 수 있다.

error, warning 둘다 해당되지 않으므로 본 코드 bsid 가 정상 실행되어 “I exist!” 를 외치는 걸 볼 수 있다.