catch — 스크립트 평가하고 예외 리턴 잡기

catch — 스크립트 평가하고 예외 리턴 잡기

Tcl에서 오류가 나면 기본적으로 명령 해석이 중단돼요. 하지만 어떤 작업은 실패할 수 있다는 걸 예상하고 오류를 잡아서 처리하고 싶을 때가 있죠. catch는 스크립트를 실행하면서 오류가 나도 명령 해석을 중단시키지 않고, 그 결과 코드와 결과값을 안전하게 돌려받을 수 있게 해 주는 명령입니다.

출처: catch manual page

본문

catch script ?resultVarName? ?optionsVarName?*

catch 명령은 오류 때문에 명령 해석이 중단되는 것을 막는 데 씁니다. catch는 Tcl 인터프리터를 재귀적으로 호출해 script를 실행하고, script 실행 중 어떤 오류가 발생하더라도 항상 오류를 던지지 않고 리턴합니다.

script가 오류를 던지면, catchscript 평가가 돌려준 예외 리턴 코드에 해당하는 0이 아닌 정수 값을 리턴해요. Tcl은 정상 리턴 코드를 0(TCL_OK)으로 정의합니다. 그리고 네 가지 예외 리턴 코드를 정의하는데, 1(TCL_ERROR), 2(TCL_RETURN), 3(TCL_BREAK), 4(TCL_CONTINUE)예요. 스크립트 평가 중 오류는 TCL_ERROR 리턴 코드로 나타납니다. 나머지 예외 리턴 코드는 return, break, continue 명령과 기타 문서화된 특수 상황에서 리턴돼요. Tcl 패키지는 리턴 코드로 다른 정수 값을 돌려주는 새 명령을 정의할 수 있고, return -code 명령을 쓰는 스크립트도 Tcl이 정의한 다섯 가지 외의 리턴 코드를 가질 수 있습니다.

resultVarName 인자가 주어지면, 그 이름의 변수에 스크립트 평가의 결과가 설정됩니다. 스크립트의 리턴 코드가 1(TCL_ERROR)이면 resultVarName에 저장되는 값은 오류 메시지예요. 리턴 코드가 0(TCL_OK)이면 resultVarName에는 script가 리턴한 값이 저장됩니다.

optionsVarName 인자가 주어지면, 그 이름의 변수에 script 평가가 돌려준 리턴 옵션들의 사전(dictionary)이 설정됩니다. Tcl은 이 사전에 항상 정의되는 두 항목(-code-level)을 명시해요. script 평가의 리턴 코드가 TCL_RETURN이 아닐 때 -level 항목의 값은 0이고, -code 항목의 값은 리턴 코드와 같습니다. 리턴 코드가 TCL_RETURN일 때만 -level-code의 값이 달라지며, 자세한 내용은 return 명령 문서에 설명돼 있어요.

script 평가의 리턴 코드가 TCL_ERRORoptionsVarName에 저장되는 리턴 옵션 사전에 네 개의 추가 항목이 정의됩니다: -errorinfo, -errorcode, -errorline, -errorstack.

-errorinfo 항목의 값은 오류가 발생한 문맥에 대한 더 많은 정보를 담는 형식화된 스택 트레이스예요. 이 스택 트레이스는 사람이 읽도록 만들어진 것입니다. -errorcode 항목의 값은 오류에 대한 추가 정보를 목록으로 저장한 것이에요. 프로그램이 더 처리할 수 있도록 만들어진 값이라 사람이 읽기에는 어려울 수 있습니다. -errorline 항목의 값은 오류가 발생했을 때 script의 몇 번째 줄이 평가되고 있었는지를 나타내는 정수예요. -errorstack 항목의 값은 스택을 풀어가며 쌓인 토큰-파라미터 쌍들로 이루어진 짝수 크기의 목록입니다. 토큰이 "CALL"이면 파라미터는 해당 레벨의 프로시저 이름과 인자들로 이루어진 목록이고, "UP"이면 파라미터는 이전 CALL의 상대 레벨(uplevel과 같은 방식)이에요. -errorinfo와의 주요 차이점은 다음과 같습니다:

  • 기계가 읽을 수 있는 형태라서 [foreach {tok prm} ...]로 처리하기 좋습니다.
  • 호출 지점의 정적 텍스트가 아니라 함수에 전달된 실제(치환된) 값들을 담고 있어요.
  • 스택 프레임당 한 요소만 담는 더 거친 단위라서, 예를 들어 foreach 구조에 대한 별도 요소가 없습니다.

가장 최근 오류의 -errorinfo-errorcode 항목 값은 전역 변수 ::errorInfo::errorCode의 값으로도 사용할 수 있어요. -errorstack 항목의 값은 info errorstack으로 노출됩니다.

Tcl 패키지는 리턴 옵션 사전에 다른 항목을 설정하는 명령을 제공할 수 있고, 스크립트가 return 명령으로 위에 정의된 것 외의 리턴 옵션을 설정할 수도 있습니다.

예시

catch 명령은 if 안에서 스크립트가 성공했는지에 따라 분기하는 데 쓸 수 있어요.

if { [catch {open $someFile w} fid] } {
    puts stderr "Could not open $someFile for writing\n$fid"
    exit 1
}

catch 사용의 더 복잡한 예시는 return 명령 문서에 있습니다.

더 알아보기

  • break, continue, dict, error, errorCode, errorInfo, info, return — 오류·예외 관련 명령
  • 키워드: catch, error, exception