Especificar la opción R global para el manejo de errores no catastróficos funcionó para mí, junto con un flujo de trabajo personalizado para retener información sobre el error y examinar esta información después de la falla. Actualmente estoy ejecutando R versión 3.4.1. A continuación, he incluido una descripción del flujo de trabajo que me funcionó, así como algún código que utilicé para establecer la opción de manejo de errores global en R.
Como lo tengo configurado, el manejo de errores también crea una RData archivo que contiene todos los objetos en la memoria de trabajo en el momento del error.Esta basura puede ser leído de nuevo en R utilizando load()
y luego los diversos entornos que existían en el momento del error pueden ser inspeccionados de forma interactiva utilizando debugger(errorDump)
.
me cuenta que yo era capaz de obtener los números de línea en el traceback()
salida de cualquiera de las funciones personalizadas dentro de la pila, pero sólo si utiliza la opción keep.source=TRUE
al llamar source()
de las funciones personalizadas se utilizan en mi guión. Sin esta opción, la configuración de la opción de manejo de errores global de la siguiente manera envió la salida completa del traceback()
a un registro de errores llamado error.log
, pero los números de línea no estaban disponibles.
Aquí están los pasos generales que tomé en mi flujo de trabajo y la forma en que era capaz de acceder al volcado de memoria y registro de errores después de un fallo R no interactivo.
puse lo siguiente en la parte superior de la secuencia de comandos principal que estaba llamando desde la línea de comandos. Esto establece la opción de manejo de error global para la sesión R. Mi guion principal se llamaba myMainScript.R
. Las diversas líneas en el código tienen comentarios después de ellos que describen lo que hacen. Básicamente, con esta opción, cuando R encuentra un error que provoca stop()
, se creará un rdata (* .rda) archivo de volcado de memoria de trabajo en todos los entornos activos en el directorio ~/myUsername/directoryForDump
y también escribirá un registro de errores llamado error.log
con algún útil información al mismo directorio. Puede modificar este fragmento para agregar otro tratamiento en caso de error (por ejemplo, agregar una marca de tiempo al archivo de volcado y nombres de archivo de registro de errores, etc.).
options(error = quote({
setwd('~/myUsername/directoryForDump'); # Set working directory where you want the dump to go, since dump.frames() doesn't seem to accept absolute file paths.
dump.frames("errorDump", to.file=TRUE, include.GlobalEnv=TRUE); # First dump to file; this dump is not accessible by the R session.
sink(file="error.log"); # Specify sink file to redirect all output.
dump.frames(); # Dump again to be able to retrieve error message and write to error log; this dump is accessible by the R session since not dumped to file.
cat(attr(last.dump,"error.message")); # Print error message to file, along with simplified stack trace.
cat('\nTraceback:');
cat('\n');
traceback(2); # Print full traceback of function calls with all parameters. The 2 passed to traceback omits the outermost two function calls.
sink();
q()}))
Asegúrese de que a partir de la secuencia de comandos principal y las llamadas a funciones siguientes, en cualquier momento una función se obtiene, se usa la opción keep.source=TRUE
. Es decir, para generar una función, usaría source('~/path/to/myFunction.R', keep.source=TRUE)
. Esto es necesario para que la salida traceback()
contenga números de línea. Parece que también puede establecer esta opción globalmente usando options(keep.source=TRUE)
, pero no he probado esto para ver si funciona. Si no necesita números de línea, puede omitir esta opción.
- Desde la terminal (fuera de R), llame a la secuencia de comandos principal en el modo por lotes utilizando
Rscript myMainScript.R
. Esto inicia una nueva sesión R no interactiva y ejecuta el script myMainScript.R
. El fragmento de código dado en el paso 1 que se ha colocado en la parte superior de myMainScript.R
establece la opción de manejo de errores para la sesión R no interactiva.
- se produzca un error en algún lugar dentro de la ejecución de
myMainScript.R
. Esto puede estar en el script principal en sí mismo o anidado varias funciones en profundidad. Cuando se encuentra el error, el manejo se realizará como se especifica en el paso 1, y la sesión R terminará.
- Se ha creado un archivo de volcado de RData llamado
errorDump.rda
y un registro de errores llamado error.log
en el directorio especificado por '~/myUsername/directoryForDump'
en la configuración de opción de manejo de errores global.
En su tiempo libre, inspeccione error.log
para revisar la información sobre el error, incluyendo el mensaje de error en sí y la traza completa que conduce al error. Aquí hay un ejemplo del registro que se genera por error; en cuenta los números después del carácter #
son los números de línea del error en varios puntos de la pila de llamadas:
Error in callNonExistFunc() : could not find function "callNonExistFunc"
Calls: test_multi_commodity_flow_cmd -> getExtendedConfigDF -> extendConfigDF
Traceback:
3: extendConfigDF(info_df, data_dir = user_dir, dlevel = dlevel) at test_multi_commodity_flow.R#304
2: getExtendedConfigDF(config_file_path, out_dir, dlevel) at test_multi_commodity_flow.R#352
1: test_multi_commodity_flow_cmd(config_file_path = config_file_path,
spot_file_path = spot_file_path, forward_file_path = forward_file_path,
data_dir = "../", user_dir = "Output", sim_type = "spot",
sim_scheme = "shape", sim_gran = "hourly", sim_adjust = "raw",
nsim = 5, start_date = "2017-07-01", end_date = "2017-12-31",
compute_averages = opt$compute_averages, compute_shapes = opt$compute_shapes,
overwrite = opt$overwrite, nmonths = opt$nmonths, forward_regime = opt$fregime,
ltfv_ratio = opt$ltfv_ratio, method = opt$method, dlevel = 0)
En su tiempo libre, se puede cargar errorDump.rda
en una sesión interactiva usando R load('~/path/to/errorDump.rda')
. Una vez cargado, llame al debugger(errorDump)
para buscar todos los objetos R en la memoria en cualquiera de los entornos activos. Consulte la ayuda de R en debugger()
para obtener más información.
Este flujo de trabajo es de gran ayuda cuando se ejecuta R en algún tipo de entorno de producción donde hay sesiones R no interactivos que se inician en la línea de comandos y que quieren que la información retenida sobre los errores inesperados. La capacidad de volcar la memoria a un archivo que puede usar para inspeccionar la memoria operativa en el momento del error, junto con los números de línea del error en la pila de llamadas, facilita la depuración rápida post mortem de lo que causó el error.
¿Alguna actualización? Cuatro 4 años más tarde, parece que el problema persiste, a pesar de la adopción generalizada de R. –
También tengo un guión R muy largo con muchos pequeños resultados, quiero imprimir (subrayado) (guión bajo) LINE/FILE (guión bajo) (guión bajo) (números de línea y nombre del guión) como el de C, en lugar de codificar números de línea en el código fuente. – mosh
No sé si R internamente realmente tiene una noción de 'números de línea'. Sin embargo, tiene una noción de tareas completas, es decir, tareas de nivel superior. Uno podría, por ejemplo, definir fácilmente un manejador de tareas para decirle a uno qué tarea de nivel superior falló. Por supuesto, eso no es una gran comodidad para aquellos con cadenas grandes o grandes declaraciones condicionales. – russellpierce