Skip to content

Commit 33be141

Browse files
committed
add post debugging em python sem ide
1 parent 1d415b8 commit 33be141

File tree

2 files changed

+243
-0
lines changed

2 files changed

+243
-0
lines changed
+243
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
title: Debugging em python (sem IDE)
2+
Slug: debugging-em-python-sem-ide
3+
Date: 2015-02-11 11:30
4+
Tags: python,pdb,ipython,ipdb,debugging
5+
Author: Diego Garcia
6+
7+
Github: drgarcia1986
8+
Site: http://www.codeforcloud.info
9+
Twitter: drgarcia1986
10+
Linkedin: drgarcia1986
11+
Category: debugging
12+
13+
14+
<figure style="float:right;">
15+
<img src="/images/drgarcia1986/debugging.png">
16+
</figure>
17+
</br>
18+
Um dos principais motivos que ainda levam desenvolvedores Python a recorrerem a IDEs pesadas e que requerem instalação é o **debugging**.
19+
Devs que vieram de linguagens como _DotNet_, _Java_ e _Delphi_ por exemplo, estão acostumados a IDEs super pesadas e inchadas que no final das contas, além do debugging, só servem para drenar memória RAM.
20+
Brincadeiras a parte, não a motivos para você não dar uma chance ao **VIM** ou ao **Sublime**, pois para fazer debugging em scripts python, tudo que você precisa é o **PDB**.
21+
22+
<!-- MORE -->
23+
24+
# PDB
25+
O `pdb` é um módulo _buit-in_ que funciona como um console interativo, onde é posssível realizar debug de códigos python.
26+
Nele é possível fazer um _step-by-step_ do código, verificando o valor de variaveis, definindo breakpoints, manipulando valores, etc.
27+
É possível inclusive realizer _step-into_ em métodos. Ou seja, tudo que uma boa ferramenta de debug precisa ter.
28+
29+
## Comandos
30+
Antes de partirmos para prática, é importante conhecer alguns comandos básicos para já começar o uso do pdb de forma efetiva.
31+
32+
Durante o debugging, eventualmente seu script irá _estacionar_ em pontos de paradas, possívelmente definidos por você, neste momento, os comandos a seguir poderão ser utilizados.
33+
34+
### q (quit)
35+
Sai da execução do script.
36+
37+
### n (next)
38+
Avança para a próxima linha do script.
39+
40+
### p (print)
41+
Executa o comando `print` do python, por exemplo:
42+
```python
43+
> /script.py(1)<module>()
44+
-> foo = "foo var"
45+
(Pdb) p foo
46+
'foo var'
47+
```
48+
> Vale ressaltar que no exemplo acima, não é necessário utilizar o comando `p`, basta digitar o nome da variável e pressionar `enter`, o efeito seria o mesmo.
49+
### c (continue)
50+
Avança o debug até o próximo **breakpoint** ou até ocorrer uma **exception**.
51+
52+
### l (list)
53+
Lista algumas linhas do código que estão em volta da linha atual.
54+
Por padrão serão apresentadas 11 linhas (5 a cima e 5 a baixo).
55+
56+
### s (step into)
57+
Ao realizar a navegação através do comando `n` o debug **não** irá _entrar_ em métodos que possívelmente forem invocados.
58+
Para que o debug entre no método que está sendo invocado na linha corrente, basta trocar o comando `n`, pelo comando `s`.
59+
```python
60+
> /home/user/foo.py(20)<module>()
61+
-> foo.bar('barz')
62+
(Pdb) s
63+
--Call--
64+
> /home/user/foo.py(3)bar()
65+
-> def bar(self, the_bar):
66+
(Pdb)
67+
```
68+
69+
### r (return)
70+
Já o comando `r` libera a execução do script até sair da função atual.
71+
72+
### b (breakpoint)
73+
Cria um breakpoint em uma determinada linha ou método, por exemplo.
74+
```python
75+
> /script.py(1)<module>()
76+
(Pdb) b 21
77+
Breakpoint 1 at /script.py:21
78+
```
79+
No comando a cima, setamos um breakpoint na linha 21 de nosso script.
80+
```python
81+
> /script.py(1)<module>()
82+
(Pdb) b foo
83+
Breakpoint 1 at /script.py:30
84+
```
85+
Já no exemplo acima, setamos o breakpoint para o método `foo`.
86+
O pdb informa qual linha ele setou o breakpoint, em nosso exemplo o método `foo` está na linha 30 do script.
87+
88+
### a (arguments)
89+
O comando `a` mostra os argumentos que foram passados para a função atual.
90+
91+
```python
92+
> /home/user/foo.py(20)<module>()
93+
-> foo.bar('barz')
94+
(Pdb) s
95+
--Call--
96+
> /home/user/foo.py(3)bar()
97+
-> def bar(self, the_bar):
98+
(Pdb) a
99+
the_bar = "barz"
100+
```
101+
102+
### ENTER
103+
Se você precionar o `ENTER` sem nenhum comando no pdb, ele irá repetir o último comando executado.
104+
105+
## Debug na prática
106+
Vamos utilizar um script python simples e didático como exemplo.
107+
108+
```python
109+
class NumberList(object):
110+
def __init__(self):
111+
self.numbers = list()
112+
113+
def add(self, number):
114+
if not isinstance(number, (int, float)):
115+
raise TypeError
116+
self.numbers.append(number)
117+
118+
def sum(self):
119+
result = 0
120+
for i in self.numbers:
121+
result += i
122+
return result
123+
124+
125+
if "__main__" == __name__:
126+
numbers = NumberList()
127+
128+
numbers.add(5)
129+
assert numbers.sum() == 5
130+
131+
numbers.add(10)
132+
assert numbers.sum() == 15
133+
134+
print "The End"
135+
```
136+
Esse script possui uma classe chamada `NumberList` que armazena uma lista de numeros e retorna a soma deles.
137+
Além destas classe, esse script também realiza algumas operações como instaciar essa classe e realizar alguns testes de asserção.
138+
Salve esse script em um arquivo chamado `numbers.py` para ser utilizado em nossos exemplos.
139+
140+
## Modos de uso do pdb
141+
142+
Na prática o pdb se assemelha bastante ao prompt interativo do python, com a diferença dos caracteres identificadores.
143+
Enquanto que no prompt interativo do python o identificador é o `>>>`, no pdb o identificador é `(Pdb)`.
144+
Existem algumas maneiras de usar o pdb, depende da forma como você pretende realizer o debbug.
145+
146+
### pdb.py
147+
Uma delas é através da chamada do script `pdb.py` passando como paramêtro o script para ser feito do debug, por exemplo:
148+
149+
```bash
150+
python -m pdb numbers.py
151+
```
152+
Isso fará com o pdb seja iniciado na primeira linha do script `numbers.py`, no caso, a declaração da classe `NumberList()`.
153+
Caso você execute o comando `n`, a próxima linha será o `if "__main__" == __name__:` e assim por diante.
154+
Utilizando desta maneira, você pode verificar linha a linha do script ou _setar_ um breakpoint assim que entrar no debug, por exemplo, se você quer criar um breakpoint na execução do método `sum()` de uma instância da classe `NumberList()`, basta executar o comando `b numbers.sum`.
155+
156+
```python
157+
(venv)user@machine:~/$ python -m pdb numbers.py
158+
> /home/user/numbers.py(4)<module>()
159+
-> class NumberList(object):
160+
(Pdb) n
161+
> /home/user/numbers.py(20)<module>()
162+
-> if __name__ == "__main__":
163+
(Pdb) n
164+
> /home/user/numbers.py(21)<module>()
165+
-> numbers = NumberList()
166+
(Pdb) n
167+
> /home/user/numbers.py(23)<module>()
168+
-> numbers.add(5)
169+
(Pdb) b numbers.sum
170+
Breakpoint 1 at /home/user/numbers.py:13
171+
(Pdb)
172+
```
173+
174+
Ou para simplificar, também poderiamos setar o breakpoint pelo número da linha.
175+
176+
```python
177+
(venv)user@machine:~/$ python -m pdb numbers.py
178+
> /home/user/numbers.py(4)<module>()
179+
-> class NumberList(object):
180+
(Pdb) b 13
181+
Breakpoint 1 at /home/user/numbers.py:13
182+
(Pdb)
183+
```
184+
### pdb.set_trace()
185+
Outra forma é utilizando o método `set_trace()` do pacote `pdb`.
186+
Com o `pdb.set_trace()` você pode definir onde será o seu breakpoint via código, por exemplo, faremos uma alteração em nosso script para setar um breakpoint no método `NumberList().sum()`.
187+
```python
188+
import pdb
189+
190+
191+
class NumberList(object):
192+
def __init__(self):
193+
self.numbers = list()
194+
195+
def add(self, number):
196+
if not isinstance(number, (int, float)):
197+
raise TypeError
198+
self.numbers.append(number)
199+
200+
def sum(self):
201+
pdb.set_trace()
202+
203+
result = 0
204+
for i in self.numbers:
205+
result += i
206+
return result
207+
208+
"""
209+
Resto do script omitido
210+
"""
211+
```
212+
Dessa forma, ao executar o script (sem a necessidade de ser via pdb) e passar pelo método `pdb.set_trace()` será iniciado um prompt interativo do pdb.
213+
214+
```python
215+
(venv)user@machine:~/$ python numbers.py
216+
> /home/user/numbers.py(16)sum()
217+
-> result = 0
218+
(Pdb)
219+
```
220+
221+
## ipdb
222+
Uma das desvantagens do prompt interativo do python é a falta de _syntax highlighting_ e _code completion_, com o pdb não é diferente, porém, assim como podemos recorrer ao [ipython](http://ipython.org/) para isso, também podemos utilizar o [ipdb](https://github.com/gotcha/ipdb).
223+
O `ipdb` é uma espécie de wrapper para o pdb que faz uso das rotinas de debug do `IPython`.
224+
A maneira de uso se assemelha bastante ao pdb, bastando trocar o pacote `pdb` pelo pacote `ipdb`.
225+
226+
```python
227+
import ipdb
228+
229+
foo = "foo"
230+
ipdb.set_trace()
231+
bar = "bar"
232+
```
233+
234+
Para instalar o ipdb basta utilizar o `pip`
235+
236+
```
237+
pip install ipdb
238+
```
239+
Com certeza recomendo o uso do `ipdb` principalmente por ser mais intuitivo.
240+
241+
**Referências**<br \>
242+
[Documentação Oficial](https://docs.python.org/2/library/pdb.html)<br />
243+
[ipdb](https://github.com/gotcha/ipdb)
23.4 KB
Loading

0 commit comments

Comments
 (0)