Especificar a opção R global para lidar com erros não catastróficos funcionou para mim, junto com um fluxo de trabalho personalizado para reter informações sobre o erro e examinar essas informações após a falha. Atualmente, estou executando o R versão 3.4.1. Abaixo, incluí uma descrição do fluxo de trabalho que funcionou para mim, bem como alguns códigos que usei para definir a opção de tratamento de erros global em R.
Como eu configurei, o tratamento de erros também cria um arquivo RData contendo todos os objetos na memória de trabalho no momento do erro. Esse dump pode ser lido de volta em R usando load()e, em seguida, os vários ambientes que existiam no momento do erro podem ser inspecionados interativamente usando debugger(errorDump).
Observarei que consegui obter números de linha na traceback()saída de quaisquer funções personalizadas dentro da pilha, mas apenas se usasse a keep.source=TRUEopção ao chamar source()qualquer função personalizada usada em meu script. Sem essa opção, definir a opção de tratamento de erros global conforme abaixo envia a saída completa de traceback()para um log de erros denominado error.log, mas os números de linha não estão disponíveis.
Estas são as etapas gerais que executei em meu fluxo de trabalho e como consegui acessar o despejo de memória e o log de erros após uma falha R não interativa.
Coloquei o seguinte no topo do script principal que estava chamando da linha de comando. Isso define a opção de tratamento de erros global para a sessão R. Meu script principal foi chamado myMainScript.R. As várias linhas do código têm comentários após elas descrevendo o que fazem. Basicamente, com esta opção, quando R encontra um erro que dispara stop(), ele criará um arquivo de despejo RData (* .rda) da memória de trabalho em todos os ambientes ativos no diretório ~/myUsername/directoryForDumpe também escreverá um log de erro nomeado error.logcom algumas informações úteis para o mesmo diretório. Você pode modificar este trecho para adicionar outro tratamento em caso de erro (por exemplo, adicionar um carimbo de data / hora ao arquivo de despejo e nomes de arquivo de log de erro, 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()}))
Certifique-se de que a partir do script principal e de quaisquer chamadas de função subsequentes, sempre que uma função for originada, a opção keep.source=TRUEseja usada. Ou seja, para obter uma função, você usaria source('~/path/to/myFunction.R', keep.source=TRUE). Isso é necessário para que a traceback()saída contenha números de linha. Parece que você também pode definir essa opção globalmente usando options( keep.source=TRUE ), mas não testei isso para ver se funciona. Se você não precisa de números de linha, pode omitir esta opção.
- Do terminal (fora de R), chame o script principal no modo batch usando
Rscript myMainScript.R. Isso inicia uma nova sessão R não interativa e executa o script myMainScript.R. O fragmento de código fornecido na etapa 1 que foi colocado na parte superior de myMainScript.Rconfigura a opção de tratamento de erros para a sessão R não interativa.
- Encontrou um erro em algum lugar durante a execução de
myMainScript.R. Isso pode estar no próprio script principal ou em várias funções aninhadas profundamente. Quando o erro for encontrado, o tratamento será executado conforme especificado na etapa 1 e a sessão R será encerrada.
- Um arquivo de despejo RData denominado ee um
errorDump.rdalog de erro denominado error.logsão criados no diretório especificado por '~/myUsername/directoryForDump'na configuração da opção de tratamento de erros global.
No seu lazer, inspecione error.logpara revisar as informações sobre o erro, incluindo a própria mensagem de erro e o rastreamento de pilha completo que levou ao erro. Aqui está um exemplo do log gerado em caso de erro; observe que os números após o #caractere são os números da linha do erro em vários pontos da pilha de chamadas:
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)
Em seu lazer, você pode carregar errorDump.rdaem uma sessão R interativa usando load('~/path/to/errorDump.rda'). Uma vez carregado, chame debugger(errorDump)para navegar todos os objetos R na memória em qualquer um dos ambientes ativos. Consulte a ajuda do R debugger()para obter mais informações.
Esse fluxo de trabalho é extremamente útil ao executar o R em algum tipo de ambiente de produção onde você tem sessões R não interativas sendo iniciadas na linha de comando e deseja que as informações sejam retidas sobre erros inesperados. A capacidade de despejar memória em um arquivo que você pode usar para inspecionar a memória de trabalho no momento do erro, junto com os números de linha do erro na pilha de chamadas, facilita a depuração post-mortem rápida do que causou o erro.