Skopiowałem następujący kod Ruby z Internetu i wprowadziłem kilka zmian, ale to nie działa.
Co mogę zrobić, aby samodzielnie debugować program?
Skopiowałem następujący kod Ruby z Internetu i wprowadziłem kilka zmian, ale to nie działa.
Co mogę zrobić, aby samodzielnie debugować program?
Odpowiedzi:
Zainstaluj przez:
$ gem install pry
$ pry
Następnie dodaj:
require 'pry'; binding.pry
do swojego programu.
Począwszy od pry
0.12.2 jednak nie ma poleceń, takich jak nawigacja next
, break
itp Niektóre inne perełki dodatkowo zapewnić to, patrz na przykład pry-byedebug
.
binding.pry
. Zawiera również uzupełnianie kolorów, przeglądanie dokumentacji i możliwość dynamicznej edycji i ponownego wczytywania metody.
Pry
/ byebug
są świetne, ale nie jako pierwszy krok podczas debugowania. W większości przypadków zgłoszenie wyjątku za pomocą raise object.inspect
rozwiąże problem szybciej niż otwarcie sesji IRB. Zalecam używanie debugerów konsoli tylko wtedy, gdy proste rozwiązania, takie jak zgłoszenie wyjątku, nie są w stanie rozwiązać problemu.
pry
? Nie mogłem znaleźć, jak to zrobić; i tego właśnie oczekuję od debuggera.
W Rubim:
ruby -rdebug myscript.rb
następnie,
b <line>
: wstaw punkt przerwania n(ext)
lub s(tep)
ic(ontinue)
p(uts)
do wyświetlenia(jak debugowanie Perla)
W Railsach: uruchom serwer z
script/server --debugger
i dodaj debugger
kod.
-r debug
to bzdury?
facets
w wymaganiach dotyczących klejnotów, ale zakończyło się to niepowodzeniem. Dla starożytnych aplikacji Railsowych ruby-debug
jest trochę paskudny, ale spełnia swoje zadanie.
Zgodnie z zaleceniami: użyj podważenia! Mogę się tylko co do tego zgodzić.
pry jest znacznie lepszą odpowiedzią niż irb.
Musisz dodać
require 'pry'
do pliku źródłowego, a następnie wstaw punkt przerwania w kodzie źródłowym, dodając
binding.pry
w miejscu, w którym chcesz się przyjrzeć rzeczom (to jest jak wyzwalanie punktu przerwania w klasycznym środowisku IDE)
Gdy Twój program trafi do
binding.pry
linii, zostaniesz wrzucony prosto do podważonej odpowiedzi, z całym kontekstem twojego programu pod ręką, dzięki czemu możesz po prostu eksplorować wszystko dookoła, badać wszystkie obiekty, zmieniać stan, a nawet zmieniać kod w locie.
Uważam, że nie możesz zmienić kodu metody, w której się obecnie znajdujesz, więc nie możesz niestety zmienić kolejnej linii do wykonania. Ale dobry kod ruby i tak ma tendencję do składania się z jednej linii ;-)
Debugowanie przez wywołanie wyjątków jest znacznie łatwiejsze niż mrużenie oka przezprint
instrukcje dziennika, a w przypadku większości błędów jest zwykle znacznie szybsze niż otwieranie debugera irb, takiego jakpry
lubbyebug
. Te narzędzia nie zawsze powinny być pierwszym krokiem.
Exception
to i .inspect
jego wynikNajszybsza droga do debugowania Ruby (zwłaszcza Rails) kod jest raise
wyjątek wzdłuż ścieżki wykonanie kodu podczas wywoływania .inspect
na metody lub obiektu (np foo
):
raise foo.inspect
W powyższym kodzie, raise
wyzwala Exception
że wstrzymuje wykonanie kodu , i zwraca komunikat o błędzie, który dogodnie zawiera .inspect
informacje na temat obiektu / metody (tj foo
) w wierszu, który próbujesz do debugowania.
Technika ta jest przydatna do szybkiego zbadania obiektu lub metody ( np. Czy to jest nil
? ) I do natychmiastowego potwierdzenia, czy wiersz kodu jest w ogóle wykonywany w danym kontekście.
byebug
lubpry
Dopiero po uzyskaniu informacji o stanie przepływu wykonywania kodu należy rozważyć przejście do debugera ruby gem irb, takiego jak pry
lub w byebug
którym można głębiej zagłębić się w stan obiektów na ścieżce wykonywania.
Kiedy próbujesz debugować problem, dobrą radą jest zawsze: Przeczytaj! @ # $ Ing Komunikat o błędzie (RTFM)
Oznacza to, że czytanie komunikatów o błędach dokładnie i całkowicie przed podjęciem działań, tak aby zrozumieć, co próbuje powiedzieć. Podczas debugowania podczas odczytywania komunikatu o błędzie zadaj następujące pytania mentalne w podanej kolejności :
nil
? ) W śladzie stosu zwróć szczególną uwagę na linie kodu pochodzące z twojego projektu (np. Linie zaczynające się od, app/...
jeśli używasz Railsów). W 99% przypadków problem dotyczy Twojego własnego kodu.
Aby zilustrować, dlaczego tłumaczenie w tej kolejności jest ważne ...
Wykonujesz kod, który w pewnym momencie jest wykonywany jako taki:
@foo = Foo.new
...
@foo.bar
i otrzymujesz błąd, który mówi:
undefined method "bar" for Nil:nilClass
Początkujący widzą ten błąd i myślą, że problem polega na tym, że metoda bar
jest niezdefiniowana . To nie jest. W tym błędzie najważniejsza część to:
for Nil:nilClass
for Nil:nilClass
oznacza, że @foo
jest zero! @foo
nie jest Foo
zmienną instancji! Masz przedmiot, który jest Nil
. Kiedy widzisz ten błąd, to po prostu ruby próbuje ci powiedzieć, że metoda bar
nie istnieje dla obiektów tej klasy Nil
. (no cóż! ponieważ próbujemy użyć metody dla obiektu klasy Foo
nie Nil
).
Niestety, ze względu na sposób zapisu tego błędu ( undefined method "bar" for Nil:nilClass
) łatwo jest dać się zwieść myśleniu, że ten błąd ma związek z bar
bytem undefined
. Jeśli nie przeczytasz uważnie, ten błąd powoduje, że początkujący omyłkowo zagłębiają się w szczegóły bar
metody Foo
, całkowicie pomijając część błędu, która wskazuje, że obiekt jest niewłaściwej klasy (w tym przypadku: zero). To błąd, którego łatwo uniknąć, czytając w całości komunikaty o błędach.
Podsumowanie:
Zawsze uważnie przeczytaj cały komunikat o błędzie przed rozpoczęciem debugowania. Oznacza to: Zawsze najpierw sprawdź typ klasy obiektu w komunikacie o błędzie , a następnie jego metody , zanim zaczniesz szukać śladu stosu lub wiersza kodu, w którym uważasz, że może wystąpić błąd. Te 5 sekund może zaoszczędzić 5 godzin frustracji.
tl; dr: Nie mruż oczy na wydruki logów: zgłaszaj wyjątki lub używaj debuggera irb. Unikaj króliczych nory, uważnie czytając błędy przed debugowaniem.
Wydrukuj zmienne, jeśli to możliwe. (Nazywa się to debugowaniem printf) Możesz to zrobić uruchamiając
STDERR.puts x.inspect
lub
STDERR.puts "Variable x is #{x.inspect}"
Jeśli chcesz, aby było to łatwiejsze do wpisania , możesz użyć klejnotu wzorcowego .
Włącz ostrzeżenia. Jeśli używasz, ruby
uruchom go za pomocą -w
przełącznika (np ruby -w script.rb
.). Jeśli uruchamiasz go z irb i używasz wersji Ruby wcześniejszej niż 1.9.2, wpisz $VERBOSE = true
na początku sesji. Jeśli pomylisz się w zmiennej instancji, po pojawieniu się ostrzeżeń otrzymasz
ostrzeżenie: zmienna instancji
@valeus
nie została zainicjowana
Zrozum pojęcie binarnego cięcia (poniższy cytat pochodzi z Practices of an Agile Developer )
Podziel obszar problemu na pół i zobacz, która połowa zawiera problem. Następnie ponownie podziel tę połowę na pół i powtórz.
Jeśli odniesiesz sukces w przypadku binarnego cięcia, może się okazać, że jest jedna linia, która nie robi tego, czego oczekujesz. Na przykład
[1, 2, 3].include?([1,2])
daje wartość false
, nawet jeśli można by pomyśleć, że zwróci true
. W takim przypadku możesz zajrzeć do dokumentacji. Witryny internetowe zawierające dokumentację obejmują ruby-doc.org lub APIdock . W tym drugim przypadku piszesz include?
obok lupy w prawym górnym rogu i wybierz to, include?
co ma Array
pod nią (jeśli nie wiesz, jaką klasę[1, 2, 3]
jest , wpisz [1, 2, 3].class
irb), a otrzymasz ? (Array) , który opisuje, co robi.
Jeśli jednak dokumentacja nie pomoże, bardziej prawdopodobne jest, że uzyskasz dobrą odpowiedź, jeśli możesz zadać pytanie, w jaki sposób konkretna linia nie robi tego, co powinna, zamiast dlaczego cały skrypt nie robi tego, co powinno.
usuwa wszystkie rzeczy
Witamy w 2017 ^ _ ^
Okay, więc jeśli nie jesteś przeciwny wypróbowaniu nowego IDE, możesz wykonać następujące czynności za darmo .
launch.json
do korzystania "cwd"
i i "program"
pola za pomocą{workspaceRoot}
makra"showDebuggerOutput"
i ustaw je natrue
"debug.allowBreakpointsEverywhere": true
vscode
; to nie to samo, co Visual Studio . Jest darmowy, lekki i ogólnie pozytywnie oceniany.View->Extensions
.vscode
a tam będziemy tylko plik o nazwie, w launch.json
którym będziemy przechowywać kilka opcji konfiguracyjnych.
launch.json
zawartość
{
"version": "0.2.0",
"configurations":
[
{
"name": "Debug Local File",
"type":"Ruby",
"request": "launch",
"cwd": "${workspaceRoot}",
"program": "{workspaceRoot}/../script_name.rb",
"args": [],
"showDebuggerOutput": true
}
]
}
File->Preferences->Settings
(lub Ctrl,) i przewiniemy, aż dojdziesz do Debug
sekcji. Rozwiń go i poszukaj pola o nazwie "debug.allowBreakpointsEverywhere"
- wybierz to pole, kliknij małą ikonę przypominającą ołówek i ustaw na true
.Po wykonaniu wszystkich tych zabawnych rzeczy powinieneś być w stanie ustawić punkty przerwania i debugować w menu podobnym do tego w połowie 2017 r. I ciemniejszym motywie: ze wszystkimi zabawnymi rzeczami, takimi jak stos wywołań, przeglądarka zmiennych itp.
Największe PITA to 1) zainstalowanie wymagań wstępnych i 2) Pamiętanie o skonfigurowaniu .vscode\launch.json
pliku. Tylko # 2 powinien dodać bagaż do przyszłych projektów i możesz po prostu skopiować wystarczająco ogólną konfigurację, taką jak wymieniona powyżej. Prawdopodobnie jest bardziej ogólna lokalizacja konfiguracji, ale nie wiem od początku mojej głowy.
Gorąco polecam ten film, aby w tej chwili wybrać odpowiednie narzędzie do debugowania naszego kodu.
https://www.youtube.com/watch?v=GwgF8GcynV0
Osobiście przedstawiłbym dwa duże tematy w tym filmie.
To moje dwa centy!
Wszystkie inne odpowiedzi dają już prawie wszystko ... Tylko mały dodatek.
Jeśli potrzebujesz więcej debuggera podobnego do IDE (nie-CLI) i nie boisz się używać Vima jako edytora, sugeruję wtyczkę Vim Ruby Debugger .
Jego dokumentacja jest dość prosta, więc kliknij link i zobacz. Krótko mówiąc, pozwala ustawić punkt przerwania w bieżącej linii w edytorze, przeglądać zmienne lokalne w sprytnym oknie podczas pauzy, przechodzić / przechodzić do - prawie wszystkie zwykłe funkcje debuggera.
Dla mnie używanie tego debuggera vim do debugowania aplikacji Railsów było całkiem przyjemne, chociaż bogate możliwości rejestratora Railsów prawie eliminują jego potrzebę.
Właśnie odkryłem ten klejnot (zmienia Pry w debugger dla MRI Ruby 2.0+)
https://github.com/deivid-rodriguez/pry-byebug
Zainstaluj za pomocą:
gem install pry-byebug
następnie użyj dokładnie tak pry
, jak zaznacz linię, w której chcesz przerwać:
require 'pry'; binding.pry
W przeciwieństwie wanilia pry jednak ten klejnot ma kilka kluczowych GDB-jak nawigacja poleceń takich jak next
, step
i break
:
break SomeClass#run # Break at the start of `SomeClass#run`.
break Foo#bar if baz? # Break at `Foo#bar` only if `baz?`.
break app/models/user.rb:15 # Break at line 15 in user.rb.
break 14 # Break at line 14 in the current file.
-w
flagę (ostrzeżenia)irb
to świetne miejsce na start. Spróbuj użyć irb z małymi wątpliwymi fragmentami. Uwielbiam ruby-debug (ruby-debug19 dla Ruby 1.9+), ponieważ ułatwia zatrzymanie uruchomionego programu, sprawdzenie zmiennych, przejście do irb, a następnie kontynuowanie działania.
Aby łatwo debugować skrypt powłoki Ruby, po prostu zmień jego pierwszą linię z:
#!/usr/bin/env ruby
do:
#!/usr/bin/env ruby -rdebug
Następnie za każdym razem, gdy zostanie wyświetlona konsola debugera, możesz wybrać:
c
dla Kontynuuj (do następnego wyjątku, punktu przerwania lub linii z:) debugger
,n
dla następnej linii,w
/ where
do wyświetlania ramki / stosu wywołań,l
aby pokazać aktualny kod,cat
aby pokazać punkty zaczepienia.h
aby uzyskać dodatkową pomoc.Zobacz też: Debugowanie za pomocą ruby-debug , Skróty klawiszowe dla ruby-debug gem .
W przypadku, gdy skrypt po prostu się zawiesił i potrzebujesz śledzenia wstecznego, spróbuj użyć lldb
/ gdb
like:
echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -nf ruby)
a następnie sprawdź pierwszy plan procesu.
Wymień lldb
się gdb
jeśli działa lepiej. Prefiks z, sudo
aby debugować proces nienależący do firmy.
Od wersji 2.4.0 Rubiego łatwiej jest rozpocząć sesję IRB REPL w środku dowolnego programu Ruby. Umieść te wiersze w punkcie programu, który chcesz debugować:
require 'irb'
binding.irb
Możesz uruchomić kod Ruby i wydrukować zmienne lokalne. Naciśnij Ctrl + D lub, quit
aby zakończyć REPL i pozwolić programowi Ruby działać dalej.
Możesz także użyć puts
i, p
aby wydrukować wartości z programu w trakcie jego działania.
Jeśli używasz RubyMine , debugowanie skryptów Ruby jest proste i nieskomplikowane.
Załóżmy, że masz skrypt Ruby hello_world.rb
Ustaw punkt przerwania w linii 6, jak poniżej.
Teraz możesz po prostu uruchomić debuger, aby uruchomić skrypt:
Następnie, gdy wykonanie osiągnie punkt przerwania, będziesz mógł sprawdzić zmienne itp.
debugowanie printf
Zawsze istniały kontrowersje wokół technik debugowania, niektórzy ludzie lubią debugować za pomocą instrukcji print, inni lubią kopać głęboko za pomocą debugera.
Sugerowałbym wypróbowanie obu podejść.
Właściwie jeden ze starych ludzi od Uniksa powiedział niedawno, że debugowanie printf było w niektórych przypadkach szybszym sposobem.
Ale jeśli jesteś nowy w jakiejś pracy i musisz zrozumieć dużą porcję kodu, to naprawdę przydatne jest przejście przez to, umieszczanie punktów przerwania tu i tam, i śledzenie, jak to działa.
Powinien dać ci trochę zrozumienia, jak tkany jest kod.
Jeśli jesteś nowy w oprogramowaniu innych ludzi, może ci to pomóc.
Szybko dowiesz się, czy sprytnie to ułożyli, czy to tylko kupa gówna.
Cóż, biblioteka Ruby standard ma łatwy w użyciu debugger konsoli podobny do gdb: http://ruby-doc.org/stdlib-2.1.0/libdoc/debug/rdoc/DEBUGGER__.html Nie ma potrzeby instalowania żadnych dodatkowych klejnotów. W ten sposób można również debugować skrypty Railsowe.
na przykład
def say(word)
require 'debug'
puts word
end
Matką wszystkich debuggerów jest zwykły stary ekran wydruku. W większości przypadków prawdopodobnie chcesz sprawdzić tylko niektóre proste obiekty, szybki i łatwy sposób jest następujący:
@result = fetch_result
p "--------------------------"
p @result
Spowoduje to wydrukowanie zawartości @result na STDOUT z linią z przodu w celu łatwej identyfikacji.
Bonus, jeśli korzystasz z platformy obsługującej automatyczne ładowanie / ponowne ładowanie, takiej jak Rails, nie musisz nawet ponownie uruchamiać aplikacji. (O ile kod, który debugujesz, nie zostanie ponownie załadowany z powodu ustawień specyficznych dla platformy)
Uważam, że działa to dla mnie w 90% przypadków użycia. Możesz także użyć ruby-debug, ale uważam, że przez większość czasu jest to przesada.
Istnieje wiele debuggerów z różnymi funkcjami, na podstawie których dokonujesz wyboru. Moje priorytety były zadowalające z ruchami podważającymi, które były: