Określenie globalnej opcji R do obsługi błędów innych niż katastrofa działało w moim przypadku, wraz ze dostosowanym przepływem pracy do przechowywania informacji o błędzie i sprawdzania tych informacji po awarii. Obecnie używam wersji R 3.4.1. Poniżej zamieściłem opis przepływu pracy, który działał dla mnie, a także kod, którego użyłem do ustawienia opcji globalnej obsługi błędów w R.
Jak skonfigurowałem, obsługa błędów tworzy również plik RData zawierający wszystkie obiekty w pamięci roboczej w momencie wystąpienia błędu. Ten zrzut można wczytać z powrotem do load()
języka R za pomocą, a następnie można interaktywnie sprawdzić różne środowiska, jakie istniały w momencie wystąpienia błędu debugger(errorDump)
.
Zwrócę uwagę, że udało mi się uzyskać numery wierszy w danych traceback()
wyjściowych z dowolnych funkcji niestandardowych w stosie, ale tylko wtedy, gdy użyłem tej keep.source=TRUE
opcji podczas wywoływania source()
jakichkolwiek funkcji niestandardowych używanych w moim skrypcie. Bez tej opcji ustawienie opcji globalnej obsługi błędów, jak poniżej, wysłało pełne dane wyjściowe traceback()
do dziennika błędów o nazwie error.log
, ale numery wierszy nie były dostępne.
Oto ogólne kroki, które wykonałem w moim przepływie pracy i jak mogłem uzyskać dostęp do zrzutu pamięci i dziennika błędów po nieinteraktywnej awarii języka R.
Na górze głównego skryptu, który wywoływałem z wiersza poleceń, umieściłem następujący tekst. To ustawia globalną opcję obsługi błędów dla sesji języka R. Mój główny skrypt został nazwany myMainScript.R
. Różne wiersze w kodzie mają po nich komentarze opisujące, co robią. Zasadniczo, z tą opcją, gdy R napotka błąd, który wyzwala stop()
, utworzy plik zrzutu RData (* .rda) pamięci roboczej we wszystkich aktywnych środowiskach w katalogu, ~/myUsername/directoryForDump
a także zapisze dziennik błędów nazwany error.log
z kilkoma przydatnymi informacjami do ten sam katalog. Możesz zmodyfikować ten fragment kodu, aby dodać inną obsługę w przypadku błędu (np. Dodać sygnaturę czasową do pliku zrzutu i nazwy plików dziennika błędów itp.).
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()}))
Upewnij się, że z głównego skryptu i wszelkich kolejnych wywołań funkcji, za każdym razem, gdy funkcja jest pobierana, keep.source=TRUE
używana jest opcja . To znaczy, aby utworzyć źródło funkcji, użyłbyś source('~/path/to/myFunction.R', keep.source=TRUE)
. Jest to wymagane, aby dane traceback()
wyjściowe zawierały numery wierszy. Wygląda na to, że możesz również ustawić tę opcję globalnie options( keep.source=TRUE )
, ale nie testowałem tego, aby sprawdzić, czy to działa. Jeśli nie potrzebujesz numerów linii, możesz pominąć tę opcję.
- Z terminala (poza R), wywołaj główny skrypt w trybie wsadowym, używając
Rscript myMainScript.R
. Spowoduje to uruchomienie nowej nieinteraktywnej sesji języka R i uruchomienie skryptu myMainScript.R
. Fragment kodu podany w kroku 1, który został umieszczony na górze, myMainScript.R
ustawia opcję obsługi błędów dla nieinteraktywnej sesji języka R.
- Napotkaj błąd gdzieś w trakcie wykonywania
myMainScript.R
. Może to być w samym skrypcie głównym lub głęboko zagnieżdżone kilka funkcji. Po napotkaniu błędu obsługa zostanie wykonana zgodnie z opisem w kroku 1, a sesja języka R zostanie zakończona.
- Plik zrzutu RData o nazwie
errorDump.rda
i dzienniku błędów o nazwie error.log
są tworzone w katalogu określonym '~/myUsername/directoryForDump'
w ustawieniu opcji globalnej obsługi błędów.
W wolnym czasie przejrzyj error.log
informacje o błędzie, w tym sam komunikat o błędzie i pełny ślad stosu prowadzący do błędu. Oto przykład dziennika, który jest generowany w przypadku błędu; zwróć uwagę, że liczby po #
znaku to numery wierszy błędu w różnych punktach stosu wywołań:
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)
W wolnym czasie możesz załadować errorDump.rda
do interaktywnej sesji języka R za pomocą load('~/path/to/errorDump.rda')
. Po załadowaniu wywołaj, debugger(errorDump)
aby przejrzeć wszystkie obiekty języka R w pamięci w dowolnym z aktywnych środowisk. Zobacz pomoc języka R, aby debugger()
uzyskać więcej informacji.
Ten przepływ pracy jest niezwykle pomocny podczas uruchamiania języka R w pewnym typie środowiska produkcyjnego, w którym nieinteraktywne sesje języka R są inicjowane w wierszu poleceń i chcesz zachować informacje o nieoczekiwanych błędach. Możliwość zrzutu pamięci do pliku, którego można użyć do sprawdzenia pamięci roboczej w momencie wystąpienia błędu, wraz z numerami wierszy błędu w stosie wywołań, ułatwiają szybkie debugowanie pośmiertne tego, co spowodowało błąd.