Wskazówki dotyczące debugowania Pythona [zamknięte]

164

Jakie są twoje najlepsze wskazówki dotyczące debugowania Pythona?

Proszę nie wymieniać konkretnego debuggera bez mówienia, co on właściwie potrafi.

Związane z

nieznanych
źródło

Odpowiedzi:

139

PDB

Możesz użyć modułu pdb, wstawić w pdb.set_trace()dowolnym miejscu i będzie on działał jako punkt przerwania.

>>> import pdb
>>> a="a string"
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) p a
'a string'
(Pdb)

Aby kontynuować wykonywanie, użyj c(lub contlub continue).

Możliwe jest wykonanie dowolnych wyrażeń Pythona za pomocą pdb. Na przykład, jeśli znajdziesz błąd, możesz poprawić kod, a następnie wpisać wyrażenie typu, aby uzyskać ten sam efekt w uruchomionym kodzie

ipdb to wersja pdb dla IPythona . Pozwala na użycie pdb ze wszystkimi funkcjami IPythona, w tym uzupełnianiem tabulatorów.

Możliwe jest również ustawienie pdb tak, aby automatycznie uruchamiał się w przypadku nieprzechwyconego wyjątku.

Pydb został napisany jako ulepszona wersja Pdb. Korzyści?

ghostdog74
źródło
Oto artykuł o używaniu pdb: sontek.net/debugging-python-with-pdb
sontek
Osobiście wolę ipdb .
Sardathrion - przeciwko nadużyciom SE
1
Najwyraźniej istnieje przepisanie pydb o nazwie pydbgr
Ehtesh Choudhury
SublimeText ma świetną wtyczkę do dodawania punktów przerwania Pythona do kodu: sublime.wbond.net/packages/Python%20Breakpoints
Dennis Golomazov
Jeśli tworzysz aplikację internetową, dodaj widok myserver.com/pdbw trybie debugowania, który po prostu to robi import pdb; pdb.set_trace(). Jeśli używasz Flask / Werkzeug, który ma interaktywny debugger, możesz również mieć widok, który po prostu działa assert False.
osa
78

http://pypi.python.org/pypi/pudb , pełnoekranowy, oparty na konsoli debugger Pythona.

Jego celem jest zapewnienie wszystkich niuansów nowoczesnych debugerów opartych na GUI w bardziej lekkim i przyjaznym dla klawiatury pakiecie. PuDB umożliwia debugowanie kodu w miejscu, w którym go piszesz i testujesz - w terminalu. Jeśli pracowałeś z doskonałymi (ale obecnie starożytnymi) narzędziami Turbo Pascal lub C opartymi na DOS, interfejs użytkownika PuDB może wyglądać znajomo.

zrzut ekranu pudb

Przyjemne do debugowania samodzielnych skryptów, po prostu uruchom

python -m pudb.run my-script.py
miku
źródło
Zainstaluj za pomocąpip install pudb
congusbongus,
40

Jeśli używasz pdb, możesz zdefiniować aliasy dla skrótów. Używam tych:

# Ned's .pdbrc

# Print a dictionary, sorted. %1 is the dict, %2 is the prefix for the names.
alias p_ for k in sorted(%1.keys()): print "%s%-15s= %-80.80s" % ("%2",k,repr(%1[k]))

# Print the instance variables of a thing.
alias pi p_ %1.__dict__ %1.

# Print the instance variables of self.
alias ps pi self

# Print the locals.
alias pl p_ locals() local:

# Next and list, and step and list.
alias nl n;;l
alias sl s;;l

# Short cuts for walking up and down the stack
alias uu u;;u
alias uuu u;;u;;u
alias uuuu u;;u;;u;;u
alias uuuuu u;;u;;u;;u;;u
alias dd d;;d
alias ddd d;;d;;d
alias dddd d;;d;;d;;d
alias ddddd d;;d;;d;;d;;d
Ned Batchelder
źródło
Jak zdefiniujesz ten alias?
Casebash
9
Umieść te rzeczy w ~ / .pdbrc
Ned Batchelder
w systemie Windows możesz umieścić go w ~ / _ipython / ipythonrc.ini
fastmultiplication
33

Logowanie

Python ma już doskonały wbudowany moduł logowania . Możesz tutaj użyć szablonu rejestrowania .

Moduł rejestrowania umożliwia określenie poziomu ważności; podczas debugowania możesz rejestrować wszystko, podczas gdy podczas normalnej pracy możesz rejestrować tylko krytyczne rzeczy. Możesz włączać i wyłączać różne rzeczy.

Większość ludzi po prostu używa podstawowych instrukcji print do debugowania, a następnie usuwa instrukcje print. Lepiej je zostawić, ale wyłącz je; wtedy, gdy pojawi się kolejny błąd, możesz po prostu ponownie włączyć wszystko i przejrzeć dzienniki.

Może to być najlepszy możliwy sposób debugowania programów, które muszą działać szybko, takich jak programy sieciowe, które muszą odpowiedzieć, zanim drugi koniec połączenia sieciowego wygaśnie i znika. Możesz nie mieć dużo czasu na jednoetapowe uruchamianie debuggera; ale możesz po prostu pozwolić uruchomić kod i zarejestrować wszystko, a następnie przejrzeć dzienniki i dowiedzieć się, co się naprawdę dzieje.

EDYCJA: Oryginalny adres URL szablonów to: http://aymanh.com/python-debugging-techniques

Brakuje tej strony, więc zastąpiłem ją odniesieniem do migawki zapisanej na archive.org: http://web.archive.org/web/20120819135307/http://aymanh.com/python-debugging-techniques

Na wypadek, gdyby znowu zniknął, oto szablony, o których wspomniałem. To jest kod pobrany z bloga; Nie napisałem tego.

import logging
import optparse

LOGGING_LEVELS = {'critical': logging.CRITICAL,
                  'error': logging.ERROR,
                  'warning': logging.WARNING,
                  'info': logging.INFO,
                  'debug': logging.DEBUG}

def main():
  parser = optparse.OptionParser()
  parser.add_option('-l', '--logging-level', help='Logging level')
  parser.add_option('-f', '--logging-file', help='Logging file name')
  (options, args) = parser.parse_args()
  logging_level = LOGGING_LEVELS.get(options.logging_level, logging.NOTSET)
  logging.basicConfig(level=logging_level, filename=options.logging_file,
                      format='%(asctime)s %(levelname)s: %(message)s',
                      datefmt='%Y-%m-%d %H:%M:%S')

  # Your program goes here.
  # You can access command-line arguments using the args variable.

if __name__ == '__main__':
  main()

A oto jego wyjaśnienie, jak korzystać z powyższego. Ponownie, nie mam za to uznania:


Domyślnie moduł rejestrowania wyświetla komunikaty krytyczne, komunikaty o błędach i ostrzeżenia. Aby to zmienić, aby wszystkie poziomy były drukowane, użyj:

$ ./your-program.py --logging=debug

Aby wysłać komunikaty dziennika do pliku o nazwie debug.log, użyj:

$ ./your-program.py --logging-level=debug --logging-file=debug.log

steveha
źródło
1
Problem z modułem logowania polega na tym, że mocno zrywa z Unicode i potrzebne są różne obejścia, aby działał w umiędzynarodowionych aplikacjach. Chociaż jest to nadal najlepsze rozwiązanie do logowania dla Pythona.
Jacek Konieczny
Link „szablon logowania tutaj” nie działa. Proszę zaktualizować.
Yohann
20

Możliwe jest wydrukowanie, jakie wiersze Pythona są wykonywane (dzięki Geo!). Ma dowolną liczbę aplikacji, na przykład możesz go zmodyfikować, aby sprawdzić, kiedy wywoływane są określone funkcje lub dodać coś takiego jak ##, aby śledził tylko określone linie.

code.interact przenosi Cię do interaktywnej konsoli

import code; code.interact(local=locals())

Jeśli chcesz mieć łatwy dostęp do historii swojej konsoli, spójrz na: „ Czy mogę mieć mechanizm historii taki jak w powłoce? ” (Będę musiał spojrzeć w dół).

Tłumaczowi można włączyć autouzupełnianie .

Casebash
źródło
19

ipdb jest jak pdb, z niesamowitością ipythona.

Alex Gaynor
źródło
5
Czy mógłbyś dodać więcej szczegółów na temat tego, co może zrobić?
Casebash
17

print sprawozdania

  • Niektórzy ludzie zalecają debug_printfunkcję zamiast drukowania w celu łatwego wyłączenia
  • pprintModuł nieocenione złożonych struktur
hasen j
źródło
3
+1 gdy każdy debugger zawiedzie, print jest twoim przyjacielem, tak debug_print byłby fajnym dodatkiem
Anurag Uniyal
Generalnie najpierw
drukuję, a potem debuguję,
4
Właściwie moduł dziennika właśnie to robi.
e-satis
To prawda, ale należy skonfigurować logowanie. Jak korzystać z modułu
nauczę się
print może być przydatny w prostych przypadkach, a zwłaszcza przy opracowywaniu projektów z krótkim czasem uruchamiania. Z drugiej strony może uzależniać, a używanie go przez pdb lub inny debugger w bardziej złożonych scenariuszach zwykle powoduje bóle głowy
vinilios
16

oczywisty sposób debugowania skryptu

python -m pdb script.py
  • przydatne, gdy ten skrypt zgłasza wyjątek
  • przydatne, gdy polecenie virtualenv i pdb nie działa w wersji Venvs Python.

jeśli nie wiesz dokładnie, gdzie jest ten skrypt

python -m pdb ``which <python-script-name>``
vinilios
źródło
15

PyDev

PyDev ma całkiem niezły interaktywny debugger. Zawiera wyrażenia obserwacyjne, najedź do oceny, listy wątków i stosów oraz (prawie) wszystkie zwykłe udogodnienia, których oczekujesz od nowoczesnego debugera wizualnego. Możesz nawet podłączyć się do działającego procesu i przeprowadzić zdalne debugowanie.

Jednak podobnie jak inne debugery wizualne, uważam, że jest on przydatny głównie w przypadku prostych problemów lub bardzo skomplikowanych problemów po wypróbowaniu wszystkiego innego. Nadal wykonuję większość ciężkich prac z wyrębem.

itsadok
źródło
Czy ma możliwość edycji i kontynuowania?
Casebash
@CaseBash nie, nie ma, ale ta funkcja jest planowana. Jednak nawet bez tego szybkość i łatwość ustawiania / wyłączania punktów przerwania i przeglądania wartości zmiennych jest nadal bardzo przydatna
Jiaaro
12

Winpdb jest bardzo fajny i wbrew swojej nazwie jest całkowicie wieloplatformowy.

Ma bardzo fajny debugger oparty na podpowiedziach i GUI oraz obsługuje zdalne debugowanie.

orip
źródło
@Casebash - dodano więcej szczegółów
orip
1
+1 To jedyny debugger Pythona, jaki do tej pory znalazłem, który obsługuje wielowątkowość.
Lee Netherton
Uważaj na jego „obsługę” wielowątkowości - każdy wyjątek w którymkolwiek wątku powoduje zawieszenie całego procesu. Nieźle, jeśli jesteś tego świadomy, bardzo bolesny, jeśli nie
Walt W
Projekt wygląda na martwy od kwietnia 2014
Alojz Janez
7

W Vimie mam te trzy wiązania:

map <F9> Oimport rpdb2; rpdb2.start_embedded_debugger("asdf") #BREAK<esc>
map <F8> Ofrom nose.tools import set_trace; set_trace() #BREAK<esc>
map <F7> Oimport traceback, sys; traceback.print_exception(*sys.exc_info()) #TRACEBACK<esc>

rpdb2to Remote Python Debugger, którego można używać z WinPDB, solidnym graficznym debugerem. Ponieważ wiem, że zapytasz, może zrobić wszystko, czego oczekuję od debugera graficznego :)

Używam pdbfrom, nose.toolsaby móc debugować testy jednostkowe, a także normalny kod.

Na koniec F7mapowanie wydrukuje traceback (podobny do tego, jaki otrzymujesz, gdy wyjątek przesuwa się na szczyt stosu). Zauważyłem, że jest naprawdę przydatny więcej niż kilka razy.

David Wolever
źródło
4

Definiowanie przydatnych metod repr () dla twoich klas (abyś mógł zobaczyć, czym jest obiekt) i użycie repr () lub "% r"% (...) lub "... {0! R} ..". Format (...) w wiadomościach / dziennikach debugowania jest kluczem IMHO do wydajnego debugowania.

Ponadto debuggery wymienione w innych odpowiedziach będą korzystać z metod repr ().

Jacek Konieczny
źródło
2

Pobieranie śladu stosu z działającej aplikacji w języku Python

Istnieje kilka sztuczek tutaj . Obejmują one

  • Włamanie się do interpretera / wydrukowanie śladu stosu przez wysłanie sygnału
  • Pobieranie śladu stosu z nieprzygotowanego procesu w Pythonie
  • Uruchamianie interpretera z flagami, aby był przydatny do debugowania
Casebash
źródło
2

Jeśli nie lubisz spędzać czasu w debuggerach (i nie doceniasz słabej użyteczności pdbinterfejsu wiersza poleceń), możesz zrzucić ślad wykonania i przeanalizować go później. Na przykład:

python -m trace -t setup.py install > execution.log

Spowoduje to zrzucenie wszystkich linii źródłowych setup.py install wykonania do execution.log.

Aby ułatwić dostosowywanie wyników śledzenia i pisanie własnych znaczników, umieściłem kilka fragmentów kodu w module xtrace (domena publiczna).

anatoly techtonik
źródło
1

Jeśli to możliwe, debuguję używając M-x pdbw emacsie do debugowania na poziomie źródła.

themis
źródło
1

Istnieje pełny kurs online o nazwie „ Debugowanie oprogramowania ” autorstwa Andreasa Zellera w serwisie Udacity, zawierający wskazówki dotyczące debugowania:

Podsumowanie kursu

Na tych zajęciach dowiesz się, jak systematycznie debugować programy, jak zautomatyzować proces debugowania i zbudować kilka automatycznych narzędzi do debugowania w Pythonie.

Dlaczego warto wziąć ten kurs?

Pod koniec tego kursu będziesz miał solidną wiedzę na temat systematycznego debugowania, będziesz wiedział, jak zautomatyzować debugowanie i zbudujesz kilka funkcjonalnych narzędzi do debugowania w Pythonie.

Wymagania wstępne i wymagania

Wymagana jest podstawowa znajomość programowania i języka Python na poziomie Udacity CS101 lub wyższym. Pomocna jest podstawowa znajomość programowania obiektowego.

Wysoce rekomendowane.

Udi
źródło
0

jeśli chcesz mieć ładny graficzny sposób drukowania stosu wywołań w czytelny sposób, sprawdź to narzędzie: https://github.com/joerick/pyinstrument

Uruchom z wiersza poleceń:

python -m pyinstrument myscript.py [args...]

Uruchom jako moduł:

from pyinstrument import Profiler

profiler = Profiler()
profiler.start()

# code you want to profile

profiler.stop()
print(profiler.output_text(unicode=True, color=True))

Uruchom z django:

Po prostu dodaj pyinstrument.middleware.ProfilerMiddlewaredo MIDDLEWARE_CLASSES, a następnie dodaj ?profilena końcu adresu URL żądania, aby aktywować profiler.

Niecka
źródło