Z tego, co przeczytałem, istnieją dwa sposoby debugowania kodu w Pythonie:
Z tradycyjnym debugerem, takim jak
pdb
lubipdb
. Obsługuje polecenia takie jakc
forcontinue
,n
forstep-over
,s
forstep-into
itp.), Ale nie masz bezpośredniego dostępu do powłoki IPython, która może być niezwykle przydatna do inspekcji obiektów.Korzystanie z IPython poprzez osadzanie powłoki IPython w kodzie. Możesz to zrobić
from ipython import embed
, a następnie użyćembed()
w swoim kodzie. Kiedy twój program / skrypt trafia naembed()
instrukcję, zostajesz przeniesiony do powłoki IPythona. Pozwala to na pełną inspekcję obiektów i testowanie kodu Pythona przy użyciu wszystkich zalet IPythona. Jednak podczas używaniaembed()
nie można już krok po kroku przez kod za pomocą przydatnych skrótów klawiaturowych.
Czy istnieje sposób, aby połączyć to, co najlepsze z obu światów? To znaczy
- Być w stanie przejść przez kod krok po kroku za pomocą przydatnych skrótów klawiaturowych pdb / ipdb.
- Na każdym takim kroku (np. W danej instrukcji), uzyskaj dostęp do pełnej powłoki IPythona .
Debugowanie IPythona jak w MATLAB:
Przykład tego typu „ulepszonego debugowania” można znaleźć w MATLAB-ie, gdzie użytkownik zawsze ma pełny dostęp do silnika / powłoki MATLAB-a i nadal może krok po kroku przeglądać swój kod, definiować warunkowe punkty przerwania itp. o czym rozmawiałem z innymi użytkownikami, jest to funkcja debugowania, której ludzie najbardziej tęsknią podczas przechodzenia z MATLAB na IPython.
Debugowanie IPythona w Emacsie i innych edytorach:
Nie chcę, aby to pytanie było zbyt konkretne, ale pracuję głównie w Emacsie, więc zastanawiam się, czy jest jakiś sposób, aby wprowadzić do niego tę funkcjonalność. Idealnie byłoby, gdyby Emacs (lub edytor) pozwolił programiście ustawić punkty przerwania w dowolnym miejscu kodu i komunikować się z interpreterem lub debugerem, aby zatrzymał się w wybranej lokalizacji i doprowadził do pełnego interpretera IPythona w tej lokalizacji.
!
polecenie, które wykonuje dowolne polecenie Pythona w punkcie przerwaniaOdpowiedzi:
Możesz użyć
%pdb
magii IPythona . Po prostu zadzwoń%pdb
w IPythonie, a gdy wystąpi błąd, automatycznie zostaniesz przeniesionyipdb
. Chociaż nie masz natychmiastowego wyjścia, jesteśipdb
później.Ułatwia to debugowanie poszczególnych funkcji, ponieważ wystarczy załadować plik,
%load
a następnie uruchomić funkcję. Możesz wymusić błąd zassert
we właściwym miejscu.%pdb
to magia linii. Nazwij to jak%pdb on
,%pdb 1
,%pdb off
lub%pdb 0
. Jeśli zostanie wywołany bez argumentów, działa jako przełącznik.źródło
ipython --pdb file.py -- args
ipdb i po wyjątku zostaniesz przeniesiony do ipdb. Może warto dodać do odpowiedzi.A co z ipdb.set_trace ()? W swoim kodzie:
import ipdb; ipdb.set_trace()
aktualizacja : teraz w Pythonie 3.7 możemy pisać
breakpoint()
. Działa tak samo, ale jest również posłusznaPYTHONBREAKPOINT
zmiennej środowiskowej. Ta funkcja pochodzi z tego PEP .Pozwala to na pełną kontrolę kodu i masz dostęp do poleceń, takich jak
c
(kontynuuj),n
(wykonaj następną linię),s
( przejdź do metody w punkcie) i tak dalej.Zobacz repozytorium ipdb i listę poleceń . IPython nazywa się teraz (edit: part of) Jupyter .
ps: zauważ, że polecenie ipdb ma pierwszeństwo przed kodem Pythona. Aby więc pisać
list(foo)
, potrzebujeszprint list(foo)
.Ponadto, jeśli podoba ci się zachęta ipython (jej tryby emacs i vim, historia, uzupełnienia,…) łatwo jest uzyskać to samo dla twojego projektu, ponieważ jest oparty na zestawie narzędzi podpowiedzi Pythona .
źródło
ipdb
w Emacsie, używającRealGUD
iisend-mode
robić dokładnie to, o co prosi OP.breakpoint()
jest wspaniałe. W PyCharm przenosi Cię nawet do debuggera PyCharm. Jest to również szybki sposób na wejście do debuggera PyCharm z funkcji wklejonych do konsoli.(Aktualizacja 28 maja 2016 r.) Używanie RealGUD w Emacs
Dla każdego w Emacsie ten wątek pokazuje, jak osiągnąć wszystko, co opisano w OP (i nie tylko), używając
ipdb
).isend-mode
.Połączenie tych dwóch pakietów jest niezwykle potężne i pozwala odtworzyć dokładnie zachowanie opisane w OP i zrobić jeszcze więcej.
Więcej informacji w artykule wiki RealGUD dla ipdb.
Oryginalna odpowiedź:
Po wypróbowaniu wielu różnych metod debugowania Pythona, w tym wszystkiego, o czym wspomniano w tym wątku, jednym z moich preferowanych sposobów debugowania Pythona za pomocą IPythona są wbudowane powłoki.
Definiowanie niestandardowej osadzonej powłoki IPython:
Dodaj następujący skrypt do swojego skryptu
PYTHONPATH
, aby metodaipsh()
stała się dostępna.Następnie za każdym razem, gdy chcę debugować coś w moim kodzie, umieszczam
ipsh()
bezpośrednio w miejscu, w którym muszę przeprowadzić inspekcję obiektu itp. Na przykład, powiedzmy, że chcę debugowaćmy_function
poniżejUżyj tego:
a następnie wywołuję
my_function(2)
w jeden z następujących sposobów:Niezależnie od tego, jak ją wywołam, tłumacz zatrzymuje się na linii, która mówi
ipsh()
. Gdy skończysz, możesz to zrobić,Ctrl-D
a Python wznowi wykonywanie (z wszelkimi aktualizacjami zmiennych, które wprowadziłeś). Zauważ, że jeśli uruchomisz kod ze zwykłego IPythona w powłoce IPython (przykład 2 powyżej), nowa powłoka IPython zostanie zagnieżdżona w tej, z której ją wywołałeś, co jest w porządku, ale dobrze jest być tego świadomym. Tak czy inaczej, gdy tłumacz zatrzyma się na lokalizacjiipsh
, mogę sprawdzić wartośća
(która jest2
), zobaczyć, jakie funkcje i obiekty są zdefiniowane itp.Problem:
Powyższe rozwiązanie może służyć do zatrzymania języka Python w dowolnym miejscu w kodzie, a następnie przeniesienia do pełnoprawnego interpretera IPythona. Niestety nie pozwala na dodawanie ani usuwanie punktów przerwania po wywołaniu skryptu, co jest bardzo frustrujące. Moim zdaniem to jedyna rzecz, która uniemożliwia IPythonowi stanie się świetnym narzędziem do debugowania w Pythonie.
Najlepsze, co możesz teraz zrobić:
Obejściem jest umieszczenie
ipsh()
a priori w różnych lokalizacjach, w których interpreter języka Python ma uruchamiać powłokę IPython (tj. Abreakpoint
). Następnie można „przeskakiwać” między różnymi predefiniowanymi, zakodowanymi na stałe „punktami przerwania”Ctrl-D
, które powodują wyjście z bieżącej wbudowanej powłoki IPython i zatrzymanie się ponownie, gdy interpreter dotrze do następnego wywołaniaipsh()
.Jeśli pójdziesz tą drogą, jednym ze sposobów wyjścia z trybu debugowania i zignorowania wszystkich kolejnych punktów przerwania jest użycie,
ipshell.dummy_mode = True
które spowoduje, że Python zignoruje wszelkie kolejne instancjeipshell
obiektu, który utworzyliśmy powyżej.źródło
import inspect
zanim zadziałało. Jednak wydaje mi się, że dostosowywanie wiersza poleceń nie działa.import ipdb; ipdb.set_trace()
? Może czegoś mi brakuje, ale nie widzę korzyści z twojej znacznie bardziej skomplikowanej metody.Możesz rozpocząć sesję IPython z pudb i wrócić do sesji debugowania, jak chcesz.
Przy okazji, ipdb używa IPython za kulisami i możesz faktycznie korzystać z funkcji IPythona, takich jak uzupełnianie TAB i magiczne polecenia (ta zaczyna się od
%
). Jeśli nie masz nic przeciwko ipdb, możesz uruchomić go z IPythona za pomocą poleceń takich jak%run
i%debug
. Sesja ipdb jest w rzeczywistości lepsza niż zwykła sesja IPythona w tym sensie, że można przesuwać się w górę iw dół w śledzeniu stosu itp. Czego brakuje w ipdb do „inspekcji obiektów”?Ponadto python.el dołączony do Emacsa> = 24.3 ma dobrą obsługę ipdb.
źródło
M-x ansi-term
buforze, a następnie używam trybu isend, aby powiązać moje bufory źródłowe z buforem IPython, dzięki czemu mogę wysłać kod do interpretera IPython za pomocą skrótu klawiaturowego, który automatycznie wysyła%paste
magię do bufora IPython. To pozwala mi na szybkie testowanie regionów w IPythonie. Zawsze uruchamiam swoje programy z tej powłoki IPythonarun
i używamembed()
do zatrzymania.ipdb
sesję debugowania przy użyciupython.el
i mieć takie rzeczy jaksend-region
itp do odpowiedniej powłoki? Ogólnie, gdzie mogę znaleźć więcej informacji na ten temat?%run
lub%debug
. Myślę, żeimport ipdb; ipdb.set_trace()
też działa. Nie sądzę, abyś mógł wysłać wiele linii do ipdb. To jest ograniczenie ipdb. Ale prawdopodobnie%paste
sztuczka działa. Możesz wysłać prośbę o funkcję do IPython dev.Wygląda na to, że podejście w odpowiedzi @ gaborous jest przestarzałe .
Wydaje się, że nowe podejście to:
źródło
ipdb
instrukcji w powłoce ipython podczas debugowania?Przedrostek „!” symbol do poleceń wpisywanych w pdb wydaje się mieć taki sam efekt, jak robienie czegoś w powłoce IPythona. Działa to przy dostępie do pomocy dla określonej funkcji lub nawet nazw zmiennych. Może to do pewnego stopnia ci pomoże. Na przykład,
Ale! Help (numpy.transpose) wyświetli oczekiwaną stronę pomocy na numpy.transpose. Podobnie w przypadku nazw zmiennych, powiedzmy, że masz zmienną l, wpisanie "l" w pdb wyświetla kod, ale! L wypisuje wartość l.
źródło
Czy wypróbowałeś tę wskazówkę ?
źródło
Możesz zacząć
IPython
od wewnątrzipdb
!Wywołaj
ipdb
debugger 1 :Wprowadź ipython od wewnątrz w
ipdb>
konsoli 2 :Wróć do
ipdb>
konsoli od wewnątrzIPython
:Jeśli masz szczęście, że używasz Emacsa, wszystko może być jeszcze wygodniejsze!
Wymaga to użycia
M-x shell
. Używającyasnippet
i bm , zdefiniuj następujący fragment. Spowoduje to zastąpienie tekstuipdb
w edytorzeset-trace
linią. Po wstawieniu skrawka linia zostanie podświetlona, aby była łatwo zauważalna i łatwa do nawigacji. UżyjM-x bm-next
do nawigacji.1 Wszystko w jednej linii dla łatwego usuwania. Ponieważ
imports
zdarza się to tylko raz, ten formularz zapewnia,ipdb
że zostanie zaimportowany, gdy go potrzebujesz, bez dodatkowych kosztów.2 Możesz zaoszczędzić sobie pisania, importując
IPython
w swoim.pdbrc
pliku :Pozwala to po prostu dzwonić
embed()
z wewnątrzipdb
(oczywiście tylko wtedy, gdy jest zainstalowany IPython).źródło
Jedną z opcji jest użycie IDE, takiego jak Spyder, które powinno umożliwić interakcję z kodem podczas debugowania (w rzeczywistości przy użyciu konsoli IPython). W rzeczywistości Spyder jest bardzo podobny do MATLABA, co, jak przypuszczam, było zamierzone. Obejmuje to inspektorów zmiennych, edycję zmiennych, wbudowany dostęp do dokumentacji itp.
źródło
właściwą, łatwą, fajną i dokładną odpowiedzią na to pytanie jest użycie makra% run z flagą -d.
źródło
%save /tmp/foo.py x-y
kod, który chcę uruchomić i debugować, a następnie%run -d /tmp/foo.py
ustawić punkt przerwania w dowolnym miejscu. Świetna odpowiedź!Jeśli wpiszesz exit () w konsoli embed (), kod będzie kontynuowany i przejdź do następnego wiersza embed ().
źródło
Pyzo IDE ma podobne możliwości jak OP prosiłem. Nie musisz zaczynać w trybie debugowania. Podobnie jak w MATLAB-ie, polecenia są wykonywane w powłoce. Po skonfigurowaniu punktu przerwania w jakiejś linii kodu źródłowego IDE zatrzymuje wykonywanie w tym miejscu i można również debugować i wydawać zwykłe polecenia IPythona.
Wydaje się jednak, że wejście w nie działa (jeszcze?) Dobrze (tj. Zatrzymanie się w jednej linii, a następnie przejście do innej funkcji), chyba że ustawisz inny punkt przerwania.
Mimo to, pochodzący z MATLAB, wydaje się być najlepszym rozwiązaniem, jakie znalazłem.
źródło
Od Pythona 3.2 masz
interact
polecenie, które daje dostęp do pełnej przestrzeni poleceń Python / ipython.źródło
Uruchamianie z wnętrza powłoki IPythona Emacsa i punktu przerwania ustawionego przez pdb.set_trace () powinno działać.
Sprawdzone w python-mode.el, Mx ipython RET itp.
źródło
Opracowywanie nowego kodu
Debugowanie w IPythonie
Przykład komórki:
Debugowanie istniejącego kodu
IPython w debugowaniu
pytest ... --pdbcls=IPython.terminal.debugger:TerminalPdb --pdb
breakpoint()
,python -m ipdb
, itd.Myśli o Pythonie
Zgadzam się z OP, że wiele rzeczy, które MATLAB robi dobrze, Python wciąż nie ma, a naprawdę powinien, ponieważ prawie wszystko w języku sprzyja szybkości rozwoju nad szybkością produkcji. Może kiedyś wniesie coś więcej niż trywialne poprawki błędów do CPythona.
https://github.com/ipython/ipython/commit/f042f3fea7560afcb518a1940daa46a72fbcfa68
Zobacz także Czy można uruchamiać polecenia w IPythonie z debugowaniem?
źródło