중단 / 종료 스크립트


85

몇 가지 데이터 분석을 수행하고 수백 줄 길이의 프로그램이 있습니다.

프로그램 초반에 품질 관리를하고 데이터가 충분하지 않으면 프로그램을 종료하고 R 콘솔로 돌아 가기를 원합니다. 그렇지 않으면 나머지 코드를 실행하고 싶습니다.

나는 시도했다 break, browser그리고 quit그들 중 누구도 나머지 프로그램의 실행을 중지하지 않습니다 (그리고 quit나는 일이하고 싶은 일이 아닙니다 아니라 완전히 종료 R,과 실행을 중지). 마지막 수단은 if-else다음과 같은 성명서를 작성하는 것입니다.

 if(n < 500){}
 else{*insert rest of program here*}

그러나 그것은 나쁜 코딩 습관처럼 보입니다. 내가 뭔가를 놓치고 있습니까?


4
quit대부분의 경우 나머지 프로그램의 실행을 중지합니다. 재현 가능한 예를 제공하십시오 .
Joshua Ulrich

@JakeBurkhead-위의 코드 (빈 if 문 포함)가 가장 좋은 방법입니까? @Joshua Ulrich quit는 R을 모두 종료하지만 프로그램이 내 목적을 위해 열려 있어야하므로 R 콘솔로 돌아가고 싶습니다.
user2588829 jul.

프로그램이란 무엇을 의미합니까? 작성한 함수를 실행 중이거나 스크립트에서 소싱하고 있음을 의미합니까?
Gavin Simpson

if-else는 아마도 이것을 처리하는 올바른 방법 일 것입니다. 예외는 모든 것이 올바르게 사용되는 경우 발생해서는 안되는 상황에 대한 것입니다. 일어날 수있는 일이고 처리 방법을 알고 있다면 정상적인 제어 흐름을 사용하십시오.
Matthew

답변:


59

stopifnot()프로그램이 오류를 생성 하도록하려면 함수를 사용할 수 있습니다 .

foo <- function(x) {
    stopifnot(x > 500)
    # rest of program
}

+1!이 함수 foo는 스크립트의 시작 부분으로 호출되어야하며 다른 유효성 검사 컨트롤을 포함해야합니다 ...
agstudy

22
stopifnot편리하지만을 사용하여 만들어진 응답 if(x < 500) { stop("Not enough observations in 'x': n < 500")}이 선호 될 수 있습니다. 또한 이것이 일괄 작업의 경우 오류를 발생 시키지 않고 문제 처리하는 것이 유용합니다.
Gavin Simpson

4
OP를 혼동하지 마십시오. 그가 원하는 것은 stopifnot ()이 아니라 quit () 또는 stop ()입니다.
stackoverflowuser2010

10
@ stackoverflowuser2010 그는 원하지 않는 quit(질문 참조!) 나는조차 생각하지 않는다 stop으로 stopifnot이 문제를 해결할 수있는 가장 좋은 방법입니다; stop오류가 발생하면 전체 스크립트가 중단됩니다. 동안 stopifnot(또는 stop) 도움말 영업 이익은 오류없이 정상적으로 종료하는 함수를 작성, 가장 좋아하는 것 같다, 상황의 넓은 범위에서 더 유리하다. 대용량 데이터 분석 작업을 위해 오래 실행되는 스크립트를 많이 작성했기 때문에 문제를 처리하고 깔끔하게 반환하는 대신 오류를 발생시키는 함수보다 더 성가신 것은 없습니다. 하지만 분명히 내가 ... 무슨 말인지 모르겠어요
개빈 심슨에게

@GavinSimpson 오류를 던지는 것에 대한 의견을 명확히 해 주시겠습니까? 내가 시도 stop("my message")하면 터미널에 인쇄됩니다 Error: "my message" Execution halted. 따라서 이것은 오류 메시지 출력을 보여 주지만 오류를 "발생"시키지 않는다는 뜻입니까? (즉, 호출하는 스크립트가 오류를 발생시키는 경우 중단하도록 설정된 배치 작업을 중지하지 않습니다). 감사! (지금은 Rscript로 스크립트를 호출하고 있습니다)
rrr

13

예쁘지는 않지만 여기 exit()에 나를 위해 작동하는 R 에서 명령 을 구현하는 방법이 있습니다.

exit <- function() {
  .Internal(.invokeRestart(list(NULL, NULL), NULL))
}

print("this is the last message")
exit()
print("you should not see this")

가볍게 테스트했지만 이것을 실행하면 this is the last message오류 메시지없이 스크립트가 중단됩니다.


단점은 CRAN 패키지의 코드에 허용되지 않는다는 것입니다. 따라서 CRAN에 업로드하려는 패키지에서 사용하려는 경우 R CMD CHECK.
MS Berends 2017 년

1
예, 이것은 시스템 기능처럼 보입니다. 인터프리터의 내부 세부 사항이 변경되면 깨질 수 있으므로 별도의 패키지보다는 R 코어의 일부가 더 나을 수 있습니까? R 소스 코드를 통해 다른 경로를 따라 가면서 오류 메시지가 나오지 않고 인터프리터를 종료 할 수있는 올바른 위치에 도달 할 수 있는지 확인했습니다. 거기에 도달하기 위해 찾은 방법은 그리 많지 않았습니다. 이것이 내가 사용 .invokeRestart하는 이유 .Internal입니다.
요헨

예, CRAN 정책 외에는 좋은 솔루션이라고 생각합니다! 내가 당신에게 +10 담당자를 제공하자)
MS Berends에게

기묘한. 방금 시도한 결과 마지막 출력 줄은 [1] "이것을 볼 수 없습니다"R 버전 3.4.3 (2017-11-30) 플랫폼 : x86_64-pc-linux-gnu (64-bit) Running under : Red Hat Enterprise Linux Server 릴리스 6.10 (Santiago)
CodingMatters

@aspiringGuru 방금 시도했지만 여전히 나를 위해 작동합니다. 명령을 스크립트로 실행 했습니까? 명령 줄에서 차례로 실행하는 경우 ( 예 : 복사 및 붙여 넣기 사용), 물론 exit()다음 명령 (아직 입력하지 않은)이 실행되는 것을 막을 수 없습니다 ...
jochen

12

if-else 구성을 뒤집으십시오.

if(n >= 500) {
  # do stuff
}
# no need for else

2
충분히 간단하고 이것이 제가 할 수있는 최선의 방법이라고 생각합니다. 감사합니다
user2588829 jul.

9

편집 : OP가 긴 스크립트를 실행하는 것 같습니다.이 경우 품질 관리 스크립트의 일부만 래핑하면 됩니다.

if (n >= 500) {

.... long running code here

}

함수 에서 벗어나면 return()명시 적으로 또는 암시 적으로를 원할 것입니다 .

예를 들어, 명시 적 이중 반환

foo <- function(x) {
  if(x < 10) {
    return(NA)
  } else {
    xx <- seq_len(x)
    xx <- cumsum(xx)
  }
  xx ## return(xx) is implied here
}

> foo(5)
[1] 0
> foo(10)
 [1]  1  3  6 10 15 21 28 36 45 55

에 의해 return()암시되고, 난 당신이 수행했던 것처럼 마지막 줄 것을 의미 return(xx)하지만, 호출을 떠날 약간 더 효율적입니다 return().

일부는 잘못된 스타일을 여러 번 반환하는 것을 고려합니다. 긴 함수에서는 함수가 종료되는 위치를 추적하는 것이 어렵거나 오류가 발생하기 쉽습니다. 따라서 대안은 단일 반환 지점을 가지지 만 if () else ()절을 사용하여 반환 객체를 변경하는 것 입니다. 그러한 수정 foo()

foo <- function(x) {
  ## out is NA or cumsum(xx) depending on x
  out <- if(x < 10) {
    NA
  } else {
    xx <- seq_len(x)
    cumsum(xx)
  }
  out ## return(out) is implied here
}

> foo(5)
[1] NA
> foo(10)
 [1]  1  3  6 10 15 21 28 36 45 55

나도 이것에 대해 생각했지만 OP가 기능에서 벗어나는 것에 대해 이야기하는 것은 분명하지 않습니다.
Thomas

네, 토마스가 옳습니다. 저는 기능에서 벗어나는 것에 대해 말하는 것이 아닙니다.
user2588829 jul.

1
@ user2588829 100 줄 이상의 스크립트보다는 R의 함수로 사용하는 것이 훨씬 낫습니다.
Gavin Simpson

@GavinSimpson 오, 나는 아직 R을 처음 접했기 때문에 그것을 몰랐습니다. 100 개 이상의 라인 함수로 정의하면 더 나은 방법일까요?
user2588829 2013

1
@ user2588829 예, 훨씬 좋습니다. 필요한 것을 전달할 수 있도록 함수의 인수를 제어합니다. 또한, 분석을 실행하기 위해 100 줄 이상의 코드를 소싱하는 대신 그냥 수행하는 myFun(arg1, arg2, arg3)등의 작업을 수행 하는 것이 훨씬 더 나은 방법입니다.
Gavin Simpson

9

어떤 시점에서 긴 스크립트 실행을 중지하고 싶을 수도 있습니다. 즉. C 또는 Python에서 exit ()를 하드 코딩하려는 것과 같습니다.

print("this is the last message")
stop()
print("you should not see this")

1
이 코드에서는 오류 메시지가 나타납니다 Error in eval(expr, envir, enclos) :.
jochen

2
예, 실행이 실제로 중지됩니다. 바꿀 경우 공교롭게도 stop()으로 exit()또는 please.stop.now()스크립트는 정지 (만 오류 메시지는 물론 다른의입니다).
jochen

1
@jochen stop()명령에 인용구를 추가하면 이 "오류"를 다른 메시지와 구별하는 데 도움이 될 수 있습니다. 예 : 혼자서 stop("Manual break inserted here")보다 더 많은 정보를 제공 할 수 있습니다 stop().
Omar Wasow

3

이것은 오래된 질문이지만 아직 깨끗한 해결책이 없습니다. 이것은 아마도이 특정 질문에 대한 대답이 아니지만 'R 스크립트에서 우아하게 종료하는 방법'에 대한 답변을 찾는 사람들은 아마도 여기에 도착할 것입니다. R 개발자가 exit () 함수를 구현하는 것을 잊은 것 같습니다. 어쨌든 내가 찾은 트릭은 다음과 같습니다.

continue <- TRUE

tryCatch({
     # You do something here that needs to exit gracefully without error.
     ...

     # We now say bye-bye         
     stop("exit")

}, error = function(e) {
    if (e$message != "exit") {
        # Your error message goes here. E.g.
        stop(e)
    }

    continue <<-FALSE
})

if (continue) {
     # Your code continues here
     ...
}

cat("done.\n")

기본적으로 플래그를 사용하여 지정된 코드 블록의 연속 여부를 나타냅니다. 그런 다음 stop()함수를 사용하여 사용자 지정된 메시지를 tryCatch()함수 의 오류 처리기에 전달 합니다. 오류 처리기가 정상적으로 종료하라는 메시지를 수신하면 오류를 무시하고 계속 플래그를로 설정합니다 FALSE.


0

"tools"패키지 의 pskill함수를 사용하여 R현재 프로세스를 중단하고 콘솔로 돌아갈 수 있습니다. 구체적으로, 각 스크립트의 시작 부분에서 소싱하는 시작 파일에 다음 함수가 정의되어 있습니다. 그러나 코드 시작 부분에 직접 복사 할 수도 있습니다. 그런 다음 halt()코드의 아무 지점 에나 삽입 하여 즉시 스크립트 실행을 중지합니다. 이 함수는 GNU / Linux에서 잘 작동하며 R문서 에서 판단하면 Windows에서도 작동합니다 (하지만 확인하지는 않았습니다).

# halt: interrupts the current R process; a short iddle time prevents R from
# outputting further results before the SIGINT (= Ctrl-C) signal is received 
halt <- function(hint = "Process stopped.\n") {
    writeLines(hint)
    require(tools, quietly = TRUE)
    processId <- Sys.getpid() 
    pskill(processId, SIGINT)
    iddleTime <- 1.00
    Sys.sleep(iddleTime)
}

> pskill (processId, SIGINT)는 세션을 닫고 사용자를 RStudio에서 쫓아냅니다. 그것은 .... 매우 위험하지만, 작동
Espanta

RStudio가 충돌 할 것이라는 것을 몰랐지만 동일한 문제가 stackoverflow.com/questions/32820534/… 에서 논의됩니다. Linux에서는 내 솔루션 이 제대로 작동합니다. stopifnot에 비해 장점은 stopifnot () 오류 메시지가 표시되지 않는다는 것입니다.
François Tonneau

나는 Windows에서 확인했고 그것은 미친 것처럼 행동합니다. 어쨌든 감사합니다. 나는 pskill을 좋아합니다.
Espanta

0

여기:

if(n < 500)
{
    # quit()
    # or 
    # stop("this is some message")
}
else
{
    *insert rest of program here*
}

둘 다 quit()stop(message)스크립트를 종료합니다. R 명령 프롬프트에서 스크립트를 소싱하는 경우 quit()R에서도 종료됩니다.


7
이미 게시 된 답변과 중복되는 답변을 게시하는 것은 좋지 않습니다.
Thomas

@Thomas 어떤 대답이 중복됩니까? 나는 stop과 quit를 모두 사용하고 실제로 그 차이점을 설명하는이 대답 만 봅니다.

@Thomas : 내 대답이 중복되는 대답이 무엇인지 정확히 설명하십시오.
stackoverflowuser2010

@Thomas : 당신의 비판에 대해 질문을했습니다. 나는 당신이 대답하기를 기다리고 있습니다.
stackoverflowuser2010

5
@ netskink의 응답 사용 stop()하고, 영업 이익은 이미 그들이 원하는하지 않는 의견에 나타난 quit()...
벤 Bolker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.