Jak wykonywać instrukcje wielowierszowe we własnym debugerze Pythona (PDB)

157

Więc uruchamiam skrypt w języku Python, w ramach którego wywołuję debugger języka Python, PDB, pisząc:

import ipdb; ipdb.set_trace()

(Wersja PDB iPythona, chociaż nie sądzę, żeby to miało znaczenie; używam go tylko do kolorowego wyjścia).

Teraz, kiedy dojdę do debugera, chcę wykonać instrukcję wielowierszową, taką jak klauzula if lub pętla for, ale gdy tylko wpiszę

if condition:

i naciskam klawisz powrotu, pojawia się komunikat o błędzie *** SyntaxError: invalid syntax (<stdin>, line 1)

Jak można wykonywać wielowierszowe instrukcje w PDB? Jeśli nie jest to możliwe, czy istnieje sposób na obejście tego, aby nadal wykonywać klauzulę if lub pętlę for?

Mikrofon
źródło

Odpowiedzi:

265

Możesz to zrobić będąc w pdb, aby uruchomić tymczasową interaktywną sesję Pythona ze wszystkimi dostępnymi zmiennymi lokalnymi:

(pdb) !import code; code.interact(local=vars())
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 

Kiedy skończysz, użyj Ctrl-D, aby powrócić do zwykłego monitu pdb.

Po prostu nie naciskaj Ctrl-C, to zakończy całą sesję pdb.

Marius Gedminas
źródło
46
Wydaje się, że to samo można osiągnąć za pomocą interactpolecenia pdb ( jak dowiedziałem się z tego komunikatu śledzenia błędów ).
gerrit
3
Dlaczego jest to !potrzebne w importoświadczeniu?
Indradhanush Gupta
19
Prawdopodobnie nie jest to potrzebne, ale mam zwyczaj poprzedzać wszystkie instrukcje Pythona w pdb !, aby uniknąć wypadków. Np. c = 42W pdb kontynuowałoby wykonywanie zamiast przypisywania do zmiennej c.
Marius Gedminas
8
@MariusGedminas najbardziej frustrująca rzecz z PDB! Byłoby miło, gdyby ich polecenia musiały być poprzedzone ...
Ian Clark
Uwaga: Ctrl-D wydaje się być również właściwym sposobem na wyjście interact, ale dla mnie nie działa dobrze ze Spyderem.
Josiah Yoder
69

W python3 ipdb(i pdb) mamy polecenie o nazwie interact . Może służyć do:

Uruchom interaktywny interpreter (używając modułu kodu ), którego globalna przestrzeń nazw zawiera wszystkie (globalne i lokalne) nazwy znalezione w bieżącym zakresie.

Aby z niego skorzystać, po prostu wpisz interactw wierszu polecenia pdb. Jest to przydatne między innymi do stosowania kodu obejmującego wiele linii, a także do unikania przypadkowego wyzwalania innych poleceń pdb.

vaer-k
źródło
2
Kiedy to robię, otrzymuję komunikat „NameError: name 'interact' is not specified".
Jason,
1
@jason w wersji 3.2 lub nowszej
vaer-k
2
To wyjaśnia. Byłem w Pythonie 2.7.
Jason,
Ostrożnie, to faktycznie spowodowało błąd, że interakcja nie została zdefiniowana i zakończyła proces
Camron_Godbout
1
Myślę, że sugerowanie unikania interactjest zbyt mocną sugestią. 90% to wszystko, czego kiedykolwiek potrzebuję, a from IPython import embed; embed()
pisanie
43

Moją rekomendacją jest użycie osadzania IPython.

ipdb> from IPython import embed; embed()
fx-kirin
źródło
2
Jeśli masz wartość nie jest zdefiniowana jako błąd w zrozumieniu listy, spróbuj użyć z IPython import embed; embed(user_ns=locals()).
fx-kirin
1
to działa dla mnie znacznie lepiej niż zaakceptowana odpowiedź. Na przykład - pozwala na poprawną edycję multilinii - jak cofnięcie się o kilka linii i naprawienie czegoś, żeby nie trzeba było ponownie przepisywać całego wyrażenia wieloliniowego ... przekazuję lokalne jako @ fx-kirin zasugerował.
ZeDuS
33

Wewnątrz interpretera lub debugera języka Python (2.7.1) (import pdb) można wykonać instrukcję wielowierszową o następującej składni.

for i in range(5): print("Hello"); print("World"); print(i)

Uwaga: kiedy jestem wewnątrz interpretera, muszę dwukrotnie nacisnąć klawisz Return, zanim kod zostanie wykonany. Jednak w debugerze muszę tylko raz nacisnąć klawisz powrotu.

Garrett Hyde
źródło
5
Nie pozwala na prowadzenie niczego głębszego niż jeden poziom.
Antony Hatchkins,
7

Jest to specjalny przypadek, jeśli chcesz, aby kilka poleceń zostało wykonanych po uderzeniu w punkt przerwania. Następnie jest polecenie debugera commands. Umożliwia wprowadzenie wielu wierszy poleceń, a następnie zakończenie całej sekwencji endsłowem kluczowym. Więcej z (pdb) help commands.

ThomasH
źródło
2

Nie wiem, czy możesz to zrobić, ale to byłaby świetna funkcja dla ipdb. Możesz oczywiście używać list składanych i wykonywać proste wyrażenia wielowierszowe, takie jak:

if y == 3: print y; print y; print y;

Możesz również wcześniej napisać kilka funkcji, aby zrobić wszystko, co potrzebujesz, co normalnie zajmie wiele linii.

zeekay
źródło