<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Danilo Cabello &#187; pdb</title>
	<atom:link href="http://blog.danilocabello.com/etiqueta/pdb/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.danilocabello.com</link>
	<description>Barba, Cabello e bigode</description>
	<lastBuildDate>Sun, 18 Jul 2010 22:17:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1-alpha</generator>
		<item>
		<title>Debugando no Django com winpdb</title>
		<link>http://blog.danilocabello.com/arquivo/debugando-no-django-com-winpdb/</link>
		<comments>http://blog.danilocabello.com/arquivo/debugando-no-django-com-winpdb/#comments</comments>
		<pubDate>Sat, 26 Sep 2009 00:11:07 +0000</pubDate>
		<dc:creator>Danilo Cabello</dc:creator>
				<category><![CDATA[Sem categoria]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[pdb]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[winpdb]]></category>

		<guid isPermaLink="false">http://blog.danilocabello.com/?p=325</guid>
		<description><![CDATA[Continuando o post anterior[1], além do pdb[2] que é totalmente via linha de comando, há o winpdb[3] que possui uma interface gráfica para facilitar a depuração. Instalá-lo é muito fácil, se você possui easy_install é só executar: sudo easy_install winpdb &#8230; <a href="http://blog.danilocabello.com/arquivo/debugando-no-django-com-winpdb/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Continuando o <a href="http://blog.danilocabello.com/arquivo/debugando-no-django/">post anterior</a>[1], além do <a href="http://docs.python.org/library/pdb.html">pdb</a>[2] que é totalmente via linha de comando, há o <a href="http://winpdb.org/">winpdb</a>[3] que possui uma interface gráfica para facilitar a depuração.</p>
<p>Instalá-lo é muito fácil, se você possui <code>easy_install</code> é só executar:</p>
<pre class="brush: bash;">
sudo easy_install winpdb
</pre>
<p>Se você não tem <code>easy_install</code>, mas tem <code>apt-get</code>:</p>
<pre class="brush: bash;">
sudo apt-get install winpdb
</pre>
<p>Se você não tem nada disso ainda dá pra baixar pelo <a href="http://winpdb.org/">site</a>[3] e funciona no Windows também, mas eu não testei.</p>
<p>Usarei como exemplo o código criado pelo <a href="http://blog.danilocabello.com/arquivo/debugando-no-django/">post anterior</a>, é um projeto bem simples com apenas uma view para atestar o poder do debug.</p>
<p>Lembra da nossa view, ela é simples assim:</p>
<pre class="brush: python;">
def hello(request):
    a = 2
    b = 3
    c = [1,2,3]
    c.pop()
    d = soma(3,4)
    response = HttpResponse(&quot;Hello World&quot;)
    return response
</pre>
<p>Como o <code>winpdb</code> possui a funcionalidade de adicionar <em>breakpoints</em> eu tirei aquele código de debug do <code>pdb</code> senão eles conflitariam entre si.</p>
<p>Abra o <code>winpdb</code>:</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/01.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/01-300x173.png" alt="winpdb" title="winpdb" width="300" height="173" class="aligncenter size-medium wp-image-327" /></a></p>
<p>A interface dele é bem simples, ficará mais clara quando estivermos executando alguma coisa.</p>
<p>Vá até <code>File->Launch</code> e na janela aberta escolha o <code>manage.py</code> do projeto que vamos depurar, por fim adicione <code>runserver --noreload</code> no comando e então clique em <code>OK</code> para iniciar o servidor.</p>
<p>O seu <code>winpdb</code> deve ficar parecido com a imagem abaixo, além de um terminal que será aberto pelo próprio <code>winpdb</code>.</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/02.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/02-300x173.png" alt="winpdb executando django runserver --noreload" title="winpdb executando django runserver --noreload" width="300" height="173" class="aligncenter size-medium wp-image-328" /></a></p>
<p>Antes de continuar qualquer coisa, vá até <code>File->Open Source</code> e na janela aberta escolha o arquivo <code>views.py</code>, adicione um <em>breakpoint</em> na linha <code>a = 2</code> clicando à direita do número da linha. Tente acessar a URL que executa a <em>view</em> <code>hello</code> e volte ao <code>winpdb</code>, você verá algo como abaixo (a diferença é que eu já andei duas linhas no código):</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/03.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/03-300x173.png" alt="winpdb na view hello" title="winpdb na view hello" width="300" height="173" class="aligncenter size-medium wp-image-329" /></a></p>
<p>Essa imagem é bem interessante pois mostra valores das variáveis, um console escondido abaixo do código, o arquivo em que o <em>debugger</em> se encontra, controles de avanço do <em>debug</em>, etc.</p>
<p>Avance com <code>Control->Next</code> até a chamada de <code>soma</code> e entre com <code>Control->Step Into</code>, avance duas linhas e você ficará assim:</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/04.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/04-300x173.png" alt="winpdb na função soma" title="winpdb na função soma" width="300" height="173" class="aligncenter size-medium wp-image-330" /></a></p>
<p>As variáveis do escopo local mudaram, o <em>debugger</em> continua no <code>views.py</code> mas agora dentro da função <code>soma</code>, dê <code>Control->Return</code> para ir até antes da função retornar pro escopo de <code>hello</code>.</p>
<p>Com <code>Control->Next</code> vá até antes da linha que executa <code>return response</code> e vamos brincar um pouco com o console que se encontra abaixo do código-fonte:</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/05.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/05-300x173.png" alt="winpdb e o console" title="winpdb e o console" width="300" height="173" class="aligncenter size-medium wp-image-331" /></a></p>
<p>Como você pode ver na imagem, o comando <code>v</code> (de <em>eval</em>) seguido de uma expressão retorna o valor da expressão, já o comando <code>x</code> (de <em>exec</em>) seguido de uma expressão executa a expressão informada.</p>
<p>Vamos fazer igual ao <a href="http://blog.danilocabello.com/arquivo/debugando-no-django/">post anterior</a> e verificar as propriedades de <code>response</code>:</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/06.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/06-300x173.png" alt="winpdb e o console alterando a response" title="winpdb e o console alterando a response" width="300" height="173" class="aligncenter size-medium wp-image-332" /></a></p>
<p>Na imagem acima, executamos um <code>dir</code> na variável <code>response</code>, exibimos seu <code>content</code> com <code>v</code>, alteramos o <code>content</code> com <code>x</code> e por fim com <code>Control->Go</code> visualizamos o resultado no navegador:</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/07.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/07-300x170.png" alt="resultado final no navegador" title="resultado final no navegador" width="300" height="170" class="aligncenter size-medium wp-image-333" /></a></p>
<p>Para saber de mais funcionalidades que o <code>winpdb</code> pode te oferecer dê uma olhada no <a href="http://winpdb.org/cgi-bin/moin.cgi/WinpdbTutorial">tutorial</a>[4] (bem completo por sinal) que se encontra na própria <a href="http://winpdb.org/cgi-bin/moin.cgi/FrontPage">wiki</a>[5] deles.</p>
<p>[1] &#8211; <a href="http://blog.danilocabello.com/arquivo/debugando-no-django/">http://blog.danilocabello.com/arquivo/debugando-no-django/</a><br />
[2] &#8211; <a href="http://docs.python.org/library/pdb.html">http://docs.python.org/library/pdb.html</a><br />
[3] &#8211; <a href="http://winpdb.org/">http://winpdb.org/</a><br />
[4] &#8211; <a href="http://winpdb.org/cgi-bin/moin.cgi/WinpdbTutorial">http://winpdb.org/cgi-bin/moin.cgi/WinpdbTutorial</a><br />
[5] &#8211; <a href="http://winpdb.org/cgi-bin/moin.cgi/FrontPage">http://winpdb.org/cgi-bin/moin.cgi/FrontPage</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.danilocabello.com/arquivo/debugando-no-django-com-winpdb/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Debugando no Django</title>
		<link>http://blog.danilocabello.com/arquivo/debugando-no-django/</link>
		<comments>http://blog.danilocabello.com/arquivo/debugando-no-django/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 03:45:20 +0000</pubDate>
		<dc:creator>Danilo Cabello</dc:creator>
				<category><![CDATA[Sem categoria]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[pdb]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.danilocabello.com/?p=311</guid>
		<description><![CDATA[Bem que você tentou, releu o código diversas vezes, escreveu um monte de prints, mas não conseguiu descobrir o que está causando aquele bug indesejado. É chegada a hora de debugar seu código, a seguir darei algumas dicas de como &#8230; <a href="http://blog.danilocabello.com/arquivo/debugando-no-django/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Bem que você tentou, releu o código diversas vezes, escreveu um monte de <em>prints</em>, mas não conseguiu descobrir o que está causando aquele bug indesejado. É chegada a hora de debugar seu código, a seguir darei algumas dicas de como debugar com pdb seu projeto em Django<a href="http://www.djangoproject.com/">[1]</a>.</p>
<p>Primeiramente, debugar um projeto em Python<a href="http://www.python.org/">[2]</a> e debugar um projeto em Django não tem muita diferença, a coisa toda é muito parecida, você só precisa do pontapé inicial para se virar dali pra frente.</p>
<p>Para aprender como utilizar o pdb<a href="http://docs.python.org/library/pdb.html">[3]</a> (vulgo Python Debugger) crie um novo projeto chamado <code>djdebug</code>, logo em seguida crie um arquivo vazio chamado <code>views.py</code> na própria raiz do projeto, ficando com a seguinte estrutura de arquivos:</p>
<pre>
djdebug
  - __init__.py
  - manage.py
  - settings.py
  - urls.py
  - views.py
</pre>
<p>No arquivo <code>views.py</code> cole o seguinte código:</p>
<pre class="brush: python;">
from django.shortcuts import HttpResponse

def soma(a,b):
    arg1 = a
    arg2 = b
    soma = arg1 + arg2
    return soma

def hello(request):
    a = 2
    b = 3
    c = [1,2,3]
    c.pop()
    d = soma(3,4)
    response = HttpResponse(&quot;Hello World&quot;)
    return response
</pre>
<p>Como podemos ver o arquivo contém uma função <code>soma</code>, que não faz nada de muito complexo e uma função <code>hello</code> que retorna uma response com o conteúdo <code>"Hello World"</code>.</p>
<p>No arquivo <code>urls.py</code> importe a view <code>hello</code> e adicione uma URL para podemos acessá-la:</p>
<pre class="brush: python;">
from views import hello

urlpatterns = patterns('',
    ...
    (r'^hello', hello),
)
</pre>
<p>Execute o servidor de testes, navegue até <code>http://localhost:8000/hello</code> e verifique que está tudo funcionando:</p>
<pre class="brush: bash;">
./manage runserver
</pre>
<p>Suponha que há um bug em alguma parte da view <code>hello</code> e então adicione o código para possibilitar o debug:</p>
<pre class="brush: python;">
def hello(request):
    a = 2
    import pdb
    pdb.set_trace()
    ...
</pre>
<p>Apenas para esclarecer, o <code>import pdb</code> importa o Python debugger, já o <code>pdb.set_trace()</code> serve pra colocar um breakpoint no código, há maneiras de se colocar um breakpoint no código sem alterá-lo através do próprio pdb<a href="http://docs.python.org/library/pdb.html">[3]</a>.</p>
<p>Execute o servidor de testes mas desta vez adicione o parâmetro necessário para evitar recarregamento automático do código-fonte:</p>
<pre class="brush: bash;">
./manage runserver --noreload
</pre>
<p>Abra novamente a view <code>hello</code> no seu navegador, ela ficará parada e no terminal que você iniciou o servidor o pdb<a href="http://docs.python.org/library/pdb.html">[3]</a> estará parado esperando por comandos:</p>
<pre class="brush: python;">
&gt; /home/.../djdebug/views.py(13)hello()
-&gt; b = 3
(Pdb)
</pre>
<p>Vamos começar, temos um comando interessante que é o <code>l</code> (de <em>list</em>, lista o código na região do debugger) que lista onde se encontra o debugger:</p>
<pre class="brush: python;">
(Pdb) l
  8
  9  	def hello(request):
 10  	    a = 2
 11  	    import pdb
 12  	    pdb.set_trace()
 13      -&gt;  b = 3
 14  	    c = [1,2,3]
 15  	    c.pop()
 16  	    d = soma(3,4)
 17  	    response = HttpResponse(&quot;Hello World&quot;)
 18  	    return response
</pre>
<p>É importante notar que o debugger se encontra no exato momento <strong>antes</strong> de executar a linha apontada pela seta, isto é, se executarmos <code>p</code> (de <em>print</em>, imprime a expressão passada como argumento) para inspecionarmos a variável <code>b</code>, ela não estará definida:</p>
<pre class="brush: python;">
(Pdb) p a
2
(Pdb) p b
*** NameError: NameError(&quot;name 'b' is not defined&quot;,)
</pre>
<p>Vamos para próxima linha com <code>n</code> (de <em>next</em>, segue para a próxima linha):</p>
<pre class="brush: python;">
(Pdb) n
&gt; /home/.../djdebug/views.py(14)hello()
-&gt; c = [1,2,3]
(Pdb) p b
3
</pre>
<p>Agora sim <code>b</code> já possui valor, vamos avançar até a chamada da função <code>somar</code>:</p>
<pre class="brush: python;">
(Pdb) n
&gt; /home/.../djdebug/views.py(15)hello()
-&gt; c.pop()
(Pdb) &lt;enter&gt;
&gt; /home/.../djdebug/views.py(16)hello()
-&gt; d = soma(3,4)
</pre>
<p>A partir do primeiro <code>n</code>, <code>enter</code> executará <code>n</code> novamente. Como nós não sabemos se o problema da view <code>hello</code> é a função <code>somar</code>, vamos entrar na função somar com <code>s</code> (de <em>step into</em>, entra na função, ou seja, passo a dentro) e verificar se está tudo certo:</p>
<pre class="brush: python;">
(Pdb) s
--Call--
&gt; /home/.../djdebug/views.py(3)soma()
-&gt; def soma(a,b):
(Pdb) l
  1  	  from django.shortcuts import HttpResponse
  2
  3     -&gt; def soma(a,b):
  4  	      arg1 = a
  5  	      arg2 = b
  6  	      soma = arg1 + arg2
  7  	      return soma
  8
  9  	  def hello(request):
 10  	      a = 2
 11  	      import pdb
</pre>
<p>Como podemos ver o debugger se encontra na entrada da função <code>soma</code>, damos uma &#8220;olhada por cima&#8221; e saímos da função com <code>up</code> (de up, sobe uma chamada na pilha):</p>
<pre class="brush: python;">
&gt; /home/.../djdebug/views.py(4)soma()
-&gt; arg1 = a
(Pdb) n
&gt; /home/.../djdebug/views.py(5)soma()
-&gt; arg2 = b
(Pdb) n
&gt; /home/.../djdebug/views.py(6)soma()
-&gt; soma = arg1 + arg2
(Pdb) u
&gt; /home/.../djdebug/views.py(16)hello()
-&gt; d = soma(3,4)
</pre>
<p>Como podemos ver, voltamos a view <code>hello</code>, vamos avançar até antes de retornar a resposta da requisição e atestar umas coisinhas:</p>
<pre class="brush: python;">
(Pdb) n
&gt; /home/.../djdebug/views.py(17)hello()
-&gt; response = HttpResponse(&quot;Hello World&quot;)
(Pdb) n
&gt; /home/.../djdebug/views.py(18)hello()
-&gt; return response
(Pdb) dir(response)
['__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_charset', '_container', '_convert_to_ascii', '_get_content', '_headers', '_is_string', '_set_content', 'close', 'content', 'cookies', 'delete_cookie', 'flush', 'get', 'has_header', 'items', 'next', 'set_cookie', 'status_code', 'tell', 'write']
(Pdb) response.content
'Hello World'
(Pdb) response.content = 'Django debugado'
(Pdb) c
</pre>
<p>Como podemos verificar, o pdb<a href="http://docs.python.org/library/pdb.html">[3]</a> fornece um shell do Python<a href="http://www.python.org/">[2]</a> você pode executar <code>dir</code>, verificar valores de variáveis e até mudar conteúdo de variáveis (poder e perigo andando juntos), por fim executamos <code>c</code> (de <em>continue</em>, para continuar a execução), veja o resultado no seu navegador, a mensagem <code>"Hello World"</code> foi trocada por <code>"Django debugado"</code>.</p>
<p>Recomendo a leitura do paper &#8220;Debugging in Python&#8221;<a href="http://www.ferg.org/papers/debugging_in_python.html">[4]</a> para mais alguns detalhes do pdb<a href="http://docs.python.org/library/pdb.html">[3]</a>. É muito interessante saber &#8220;brincar&#8221; com o shell do Python e do Django, com essas ferramentas fica mais fácil rastrear o chato do bug.</p>
<p>[1] -<a href="http://www.djangoproject.com/"> http://www.djangoproject.com/</a><br />
[2] &#8211; <a href="http://www.python.org/">http://www.python.org/</a><br />
[3] &#8211; <a href="http://docs.python.org/library/pdb.html">http://docs.python.org/library/pdb.html</a><br />
[4] &#8211; <a href="http://www.ferg.org/papers/debugging_in_python.html">http://www.ferg.org/papers/debugging_in_python.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.danilocabello.com/arquivo/debugando-no-django/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
