Narzędzia użytkownika

Narzędzia witryny


debugowanie_w_rstudio

Debugowanie w RStudio

Debugowanie R nie należy do najprzyjemniejszych, ale zarówno RStudio, jak i zmiany w R w wersji 3.1 przyniosły wiele dobrego - trzeba się tylko nauczyć, jak z tego korzystać.

W dalszej części korzystać będę z nomenklatury RStudio, czyli np. mówić o breakpoint-ach bez wchodzenia w to, jak tak naprawdę są one realizowane na poziomie R.

Jak debuguje się w RStudio?

Co nas denerwuje w debugowaniu w R?

Brak komendy step into

Podczas wykonywania krokowego nie ma długo nie było łatwego sposobu na przejście do krokowego wykonywania wywoływanej funkcji (brak komendy step into debugera).

  • W R 3.1 pojawiła się komenda step into (s).
  • Wcześniej niezbędne było wstawianie breakpoint-ów wewnątrz każdej funkcji, którą potencjalnie chcieliśmy debugować.
    • Jeśli była to funkcja anonimowa, było to niemożliwe.

Nie da się zdefiniować breakpoint-a wewnątrz funkcji anonimowej

W R 3.1 już można!

Możliwe obejścia we wcześniejszych wersjach:

  • Wstawienie wewnątrz funkcji anonimowej komendy browse().
  • W ogóle nie korzystać z funkcji anonimowych, np.
    wynik = sapply(dane, function(x){ zrób coś });
    # przekształcamy na:
    policz = function(x){ zrób coś }
    wynik = sapply(dane, policz)

Funkcje R zgłaszają błędy w niezrozumiały sposób

Pisząc pakiety R, w szczególności base i stat, mało kto przejmuje się eleganckim zgłaszaniem błędów. Stąd błędy zgłaszane przez funkcje języka R na ogół odnoszą się do tego, co poszło nie tak wewnątrz danej funkcji, a nie co było nie tak w przekazanych jej parametrach, a więc niewiele mówią.

Z problemem tym stykamy się także podczas domyślnego wchodzenia w tryb debugowania przez RStudio - na ogół na ekranie wyświetlany jest nam kod jakiejś wewnętrznej funkcji R w której ostatecznie błąd się ujawnia. My tymczasem wolelibyśmy zobaczyć kod naszej funkcji, wraz ze wskazaniem linii, w której tą wewnętrzną funkcję R wywołaliśmy.

Szczęśliwie:

  • w R jest funkcja traceback() wyświetlająca stos wywołań funkcji;
  • RStudio ładnie ją obudowuje:
    • prawa szpalta → panel Environment → pole Traceback pod listą zmiennych.

Możemy się tam dowiedzieć:

  • Jaka była sekwencja wołania funkcji, tzn. jaka była ostatnia linia naszego kodu, w której coś poszło nie tak (i np. założyć tam breakpoint-a).
  • Obejrzeć, jakie były środowiska wykonania każdej z funkcji w stosie wywołań.
    • Aby to zrobić klikamy na interesującej nas funkcji stosu wywołań - pole z listą zmiennych automatycznie dostosuje swoją zawartość do kontekstu wywołania danej funkcji.
    • Umożliwia to prześledzenie argumentów wywołania funkcji, w której coś poszło nie tak.
      • Także funkcji anonimowych.

Przykrywanie kodu funkcji

RStudio nie umie rozpoznać sytuacji, w której kod funkcji z breakpoint-em został przykryty przez inny kod. Typowo sekwencja zdarzeń wygląda następująco:

  • otwieramy projekt;
  • zakładamy breakpoint w funkcji X();
  • ładujemy projekt (CTRL+SHIFT+L albo devtools::load_all());
    • RStudio pokazuje nam, że breakpoint jest aktywny;
  • zmieniamy coś na szybko w funkcji X() i wykonujemy jej kod, aby załadować jej nową wersję;
    • RStudio nadal pokazuje nam, że breakpoint jest aktywny, chociaż tak naprawdę już nie jest.

Dzieje się tak dlatego, że breakpoint można założyć tylko w kodzie wczytanym z pliku (takie są techniczne ograniczenia R), a obecny kod funkcji X() nie pochodził z wczytania danych z pliku, tylko został wprost wpisany w konsoli R.

Żeby pozbyć się problemu:

  • usuwamy definicję funkcji X() z pamięci: rm(X);
  • wczytujemy cały projekt (CTRL+SHIFT+L albo devtools::load_all()).
debugowanie_w_rstudio.txt · ostatnio zmienione: 2015/01/30 10:42 przez zozlak