Tengo un programa que hace algunos análisis de datos y tiene unos cientos de líneas.
Muy temprano en el programa, quiero hacer un control de calidad y, si no hay suficientes datos, quiero que el programa finalice y vuelva a la consola R. De lo contrario, quiero que se ejecute el resto del código.
Lo he intentado break
, browser
y quit
ninguno de ellos detener la ejecución del resto del programa (y quit
detiene la ejecución, así como dejar de fumar por completo R, que no es algo que quiero que suceda). Mi último recurso es crear una if-else
declaración de la siguiente manera:
if(n < 500){}
else{*insert rest of program here*}
pero eso parece una mala práctica de codificación. ¿Me estoy perdiendo de algo?
quit
ciertamente detiene la ejecución del resto del programa. Proporcione un ejemplo reproducible .quit
sale de todo R, pero quiero volver a la consola R porque el programa debe permanecer abierto para mis propósitos.Respuestas:
Puede usar la
stopifnot()
función si desea que el programa produzca un error:foo <- function(x) { stopifnot(x > 500) # rest of program }
fuente
foo
debería llamarse al comienzo del script y contener otro control de validaciones ...stopifnot
es útil, peroif(x < 500) { stop("Not enough observations in 'x': n < 500")}
se puede preferir una respuesta elaborada . Además, si esto es algo para un trabajo por lotes, es útil manejar el problema sin arrojar un error.quit
(¡vea la pregunta!) Ni siquiera piensostop
enstopifnot
la mejor manera de manejar esto;stop
arroja un error, todo el script simplemente abortará. Si bienstopifnot
(ostop
) parece ser la respuesta que más le gustó a OP, escribir una función para salir limpiamente, sin errores, es más beneficioso en una gama más amplia de situaciones. Habiendo escrito muchos scripts de larga duración para trabajos de análisis de datos de gran tamaño, nada es más molesto que las funciones que arrojan errores en lugar de manejar el problema y regresar limpiamente. Pero claramente no sé de qué estoy hablando ...stop("my message")
me imprimen en la terminalError: "my message" Execution halted
. Entonces, esto muestra una salida de mensaje de error, pero ¿estás diciendo que no "arroja" un error? (es decir, no detendrá un trabajo por lotes que se ha configurado para abortar si alguno de los scripts que llama arroja errores). ¡Gracias! (Ahora mismo estoy llamando al script con Rscript)No es bonito, pero aquí hay una forma de implementar un
exit()
comando en R que me funciona.exit <- function() { .Internal(.invokeRestart(list(NULL, NULL), NULL)) } print("this is the last message") exit() print("you should not see this")
Solo probado ligeramente, pero cuando ejecuto esto, veo
this is the last message
y luego el script se aborta sin ningún mensaje de error.fuente
R CMD CHECK
..invokeRestart
que a su vez parece necesitar el.Internal
.exit()
, no puede evitar que se ejecute el siguiente comando (que aún no se ha ingresado) ...Invierta su construcción if-else:
if(n >= 500) { # do stuff } # no need for else
fuente
Editar: Parece que el OP está ejecutando un script largo, en ese caso, solo se necesita envolver la parte del script después del control de calidad con
if (n >= 500) { .... long running code here }
Si se sale de una función , probablemente solo querrá
return()
, ya sea explícita o implícitamente.Por ejemplo, un retorno doble explícito
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
Al
return()
estar implícito, me refiero a que la última línea es como si lo hubiera hechoreturn(xx)
, pero es un poco más eficiente dejar la llamada areturn()
.Algunos consideran que el uso de devoluciones múltiples es de mal estilo; en funciones largas, realizar un seguimiento de dónde sale la función puede resultar difícil o propenso a errores. Por lo tanto, una alternativa es tener un único punto de retorno, pero cambiar el objeto de retorno usando la
if () else ()
cláusula. Tal modificaciónfoo()
seríafoo <- 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
fuente
myFun(arg1, arg2, arg3)
etc. Es una forma mucho mejor de organizar las cosas.Quizás solo desee dejar de ejecutar un script largo en algún momento. es decir. como si quisiera codificar una salida () en C o Python.
print("this is the last message") stop() print("you should not see this")
fuente
Error in eval(expr, envir, enclos) :
.stop()
conexit()
oplease.stop.now()
, el script también se detiene (solo los mensajes de error son, por supuesto, diferentes).stop()
comando puede ayudar a distinguir este "error" de otros mensajes. Por ejemplo:stop("Manual break inserted here")
podría ser más informativo questop()
solo.Esta es una vieja pregunta, pero aún no existe una solución clara. Esto probablemente no responde a esta pregunta específica, pero aquellos que buscan respuestas sobre 'cómo salir con gracia de un script R' probablemente aterrizarán aquí. Parece que los desarrolladores de R se olvidaron de implementar una función exit (). De todos modos, el truco que encontré es:
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")
Básicamente, usa una bandera para indicar la continuación o no de un bloque de código específico. Luego, usa la
stop()
función para pasar un mensaje personalizado al controlador de errores de unatryCatch()
función. Si el controlador de errores recibe su mensaje para salir correctamente, simplemente ignora el error y establece el indicador de continuación enFALSE
.fuente
Puede utilizar la
pskill
función en elR
paquete "herramientas" para interrumpir el proceso actual y volver a la consola. Concretamente, tengo la siguiente función definida en un archivo de inicio que obtengo al principio de cada script. Sin embargo, también puede copiarlo directamente al comienzo de su código. Luego insertehalt()
en cualquier punto de su código para detener la ejecución del script sobre la marcha. Esta función funciona bien en GNU / Linux y, a juzgar por laR
documentación, también debería funcionar en Windows (pero no lo comprobé).# 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) }
fuente
Aquí:
if(n < 500) { # quit() # or # stop("this is some message") } else { *insert rest of program here* }
Ambos
quit()
ystop(message)
saldrán de su guión. Si está obteniendo su script desde el símbolo del sistema de R, tambiénquit()
saldrá de R.fuente
stop()
, y OP ya indicó en los comentarios que no quierenquit()
...