Pelo que li, há duas maneiras de depurar código no Python:
Com um depurador tradicional como
pdb
ouipdb
. Isso suporta comandos comoc
forcontinue
,n
forstep-over
,s
forstep-into
etc.), mas você não tem acesso direto a um shell IPython que pode ser extremamente útil para inspeção de objetos.Usando o IPython , incorporando um shell IPython ao seu código. Você pode fazer
from ipython import embed
e usarembed()
no seu código. Quando seu programa / script atinge umaembed()
instrução, você é colocado em um shell IPython. Isso permite a inspeção completa dos objetos e o teste do código Python usando todas as vantagens do IPython. No entanto, ao usar,embed()
você não pode mais passo a passo através do código com atalhos de teclado úteis.
Existe alguma maneira de combinar o melhor dos dois mundos? Ou seja,
- Veja passo a passo o seu código com atalhos de teclado pdb / ipdb úteis.
- Em qualquer uma dessas etapas (por exemplo, em uma determinada instrução), tenha acesso a um shell IPython completo .
Depuração de IPython como no MATLAB:
Um exemplo desse tipo de "depuração aprimorada" pode ser encontrado no MATLAB, onde o usuário sempre tem acesso total ao mecanismo / shell MATLAB e ainda pode passo a passo através de seu código, definir pontos de interrupção condicionais etc. o que discuti com outros usuários, esse é o recurso de depuração que as pessoas mais sentem falta ao passar do MATLAB para o IPython.
Depuração de IPython no Emacs e em outros editores:
Não quero tornar a pergunta muito específica, mas trabalho principalmente no Emacs, por isso me pergunto se existe alguma maneira de trazer essa funcionalidade para ele. Idealmente , o Emacs (ou o editor) permitiria ao programador definir pontos de interrupção em qualquer lugar do código e se comunicar com o intérprete ou depurador para que ele parasse no local de sua escolha e traga para um intérprete IPython completo nesse local.
!
comando que executa qualquer comando python no ponto de interrupçãoRespostas:
Você pode usar a
%pdb
magia do IPython . Basta chamar o%pdb
IPython e, quando ocorrer um erro, você será automaticamente descartadoipdb
. Enquanto você não tem o passo imediato, você entraipdb
depois.Isso facilita a depuração de funções individuais, pois você pode carregar um arquivo
%load
e executar uma função. Você pode forçar um erro com umassert
na posição correta.%pdb
é uma mágica de linha. Chamá-lo como%pdb on
,%pdb 1
,%pdb off
ou%pdb 0
. Se chamado sem argumento, funciona como uma alternância.fonte
ipython --pdb file.py -- args
e cair para o ipdb em uma exceção. Pode valer a pena adicionar à resposta.E o ipdb.set_trace ()? No seu código:
import ipdb; ipdb.set_trace()
update : agora em Python 3.7, podemos escrever
breakpoint()
. Funciona da mesma forma, mas também obedece àPYTHONBREAKPOINT
variável de ambiente. Esse recurso vem deste PEP .Isso permite a inspeção completa do seu código, e você tem acesso a comandos como
c
(continuar),n
(executar a próxima linha),s
(entrar no método no ponto) e assim por diante.Veja o repo ipdb e uma lista de comandos . O IPython agora é chamado (edit: parte de) Jupyter .
ps: observe que um comando ipdb tem precedência sobre o código python. Então, para escrever
list(foo)
você precisariaprint list(foo)
.Além disso, se você gosta do prompt do ipython (seus modos emacs e vim, histórico, conclusões ...), é fácil obter o mesmo para o seu projeto, pois ele é baseado no kit de ferramentas do prompt do python .
fonte
ipdb
no Emacs usandoRealGUD
eisend-mode
fazer exatamente o que o OP pede.breakpoint()
é maravilhoso. No PyCharm, você ainda o coloca no depurador PyCharm. Também é uma maneira rápida de inserir o depurador PyCharm a partir de funções que foram coladas no console.(Atualização em 28 de maio de 2016) Usando o RealGUD no Emacs
Para qualquer pessoa no Emacs, este tópico mostra como realizar tudo descrito no OP (e mais) usando
ipdb
).isend-mode
.A combinação desses dois pacotes é extremamente poderosa e permite recriar exatamente o comportamento descrito no OP e fazer ainda mais.
Mais informações no artigo wiki do RealGUD para ipdb.
Resposta original:
Depois de ter tentado muitos métodos diferentes para depurar o Python, incluindo tudo mencionado neste segmento, uma das minhas maneiras preferidas de depurar o Python com o IPython é com shells incorporados.
Definindo um shell IPython incorporado personalizado:
Adicione o seguinte em um script ao seu
PYTHONPATH
, para que o métodoipsh()
fique disponível.Então, sempre que eu quiser depurar algo no meu código, coloco
ipsh()
no local onde preciso fazer a inspeção de objetos, etc. Por exemplo, digamos que quero depurarmy_function
abaixoUsando isso:
e depois invoco
my_function(2)
de uma das seguintes maneiras:Independentemente de como eu o invoque, o intérprete para na linha que diz
ipsh()
. Quando terminar, você pode fazerCtrl-D
e o Python retomará a execução (com todas as atualizações de variáveis que você fez). Observe que, se você executar o código a partir de um IPython comum, o shell IPython (caso 2 acima), o novo shell IPython será aninhado dentro daquele em que você o chamou, o que é perfeitamente aceitável, mas é bom estar ciente disso. De qualquer forma, uma vez que o intérprete para na localização deipsh
, posso inspecionar o valor dea
(qual é2
), ver quais funções e objetos são definidos etc.O problema:
A solução acima pode ser usada para que o Python pare em qualquer lugar que você queira no seu código e, em seguida, coloque você em um intérprete IPython completo. Infelizmente, ele não permite adicionar ou remover pontos de interrupção depois de chamar o script, o que é altamente frustrante. Na minha opinião, isso é a única coisa que impede o IPython de se tornar uma ótima ferramenta de depuração para o Python.
O melhor que você pode fazer por enquanto:
Uma solução alternativa é colocar
ipsh()
a priori nos diferentes locais em que você deseja que o interpretador Python inicie um shell IPython (ou seja, abreakpoint
). Você pode "pular" entre diferentes "pontos de interrupção" predefinidos e codificadosCtrl-D
, que sairiam do shell IPython incorporado atual e parariam novamente sempre que o intérprete atingir a próxima chamadaipsh()
.Se você seguir esta rota, uma maneira de sair do "modo de depuração" e ignorar todos os pontos de interrupção subseqüentes é usar o
ipshell.dummy_mode = True
que fará o Python ignorar quaisquer instâncias subsequentes doipshell
objeto que criamos acima.fonte
import inspect
antes que funcionasse. A personalização da linha de comando parece estar corrompida para mim.import ipdb; ipdb.set_trace()
? Talvez eu sinta falta de algo, mas não vejo a vantagem do seu método muito mais complicado.Você pode iniciar a sessão do IPython a partir do pudb e voltar à sessão de depuração como desejar.
BTW, o ipdb está usando o IPython nos bastidores e você pode realmente usar a funcionalidade do IPython, como a conclusão do TAB e os comandos mágicos (aquele começa com
%
). Se você concorda com o ipdb, pode iniciá-lo no IPython usando comandos como%run
e%debug
. A sessão do ipdb é realmente melhor que a do IPython comum, no sentido em que você pode subir e descer no rastreamento de pilha, etc. O que está faltando no ipdb para "inspeção de objeto"?Além disso, o python.el empacotado com o Emacs> = 24.3 possui um bom suporte ao ipdb.
fonte
M-x ansi-term
buffer separado e, em seguida, uso o modo isend para vincular meus buffers de origem ao buffer do IPython, para que eu possa enviar código ao intérprete do IPython com um atalho de teclado que envia automaticamente a%paste
mágica para o buffer do IPython. Isso me permite testar rapidamente regiões no IPython. Eu sempre executo meus programas nesse shell IPython comrun
e usoembed()
para parar.ipdb
sessão de depuração usandopython.el
e ter coisas comosend-region
etc. no shell correspondente? Em geral, onde posso encontrar mais informações sobre isso?%run
ou%debug
. Eu acho queimport ipdb; ipdb.set_trace()
funciona também. Eu não acho que você pode enviar várias linhas para o ipdb. Essa é a limitação do ipdb. Mas provavelmente o%paste
truque funciona. Você pode enviar uma solicitação de recurso para o IPython dev.Parece que a abordagem na resposta de @ gaborous está obsoleta .
A nova abordagem parece ser:
fonte
ipdb
instruções no shell do ipython durante a depuração?Prefixando um "!" O símbolo dos comandos digitados em pdb parece ter o mesmo efeito que fazer algo em um shell IPython. Isso funciona para acessar a ajuda de uma determinada função ou até nomes de variáveis. Talvez isso ajude você até certo ponto. Por exemplo,
Mas! Help (numpy.transpose) fornece a página de ajuda esperada em numpy.transpose. Da mesma forma, para nomes de variáveis, digamos que você tenha uma variável l, digitar "l" no pdb lista o código, mas! L imprime o valor de l.
fonte
Você tentou esta dica ?
fonte
Você pode começar
IPython
de dentroipdb
!Induza o
ipdb
depurador 1 :Digite IPython de dentro no
ipdb>
console 2 :Retorne ao
ipdb>
console de dentroIPython
:Se você tiver a sorte de usar o Emacs, as coisas podem ser ainda mais convenientes!
Isso requer o uso
M-x shell
. Usandoyasnippet
e bm , defina o seguinte snippet. Isso substituirá o textoipdb
no editor pelaset-trace
linha. Após inserir o trecho, a linha será destacada para que seja facilmente perceptível e navegável. UseM-x bm-next
para navegar.1 Tudo em uma linha para exclusão fácil. Como
imports
só acontece uma vez, este formulário garanteipdb
que será importado quando você precisar, sem custos adicionais.2 Você pode economizar digitando importando
IPython
para o seu.pdbrc
arquivo :Isso permite que você simplesmente chame
embed()
de dentroipdb
(é claro, somente quando o IPython estiver instalado).fonte
Uma opção é usar um IDE como o Spyder, que deve permitir que você interaja com seu código durante a depuração (usando um console IPython, de fato). Na verdade, o Spyder é muito parecido com o MATLAB, que eu presumo que foi intencional. Isso inclui inspetores variáveis, edição de variáveis, acesso interno à documentação, etc.
fonte
a resposta certa, fácil, legal e exata para a pergunta é usar% run macro com o sinal -d.
fonte
%save /tmp/foo.py x-y
O código que eu quero executar e depurar e, em seguida,%run -d /tmp/foo.py
definir o ponto de interrupção onde eu quiser. Ótima resposta!Se você digitar exit () no console embed (), o código continuará e vá para a próxima linha embed ().
fonte
O Pyzo IDE possui recursos semelhantes aos solicitados pelo OP. Você não precisa iniciar no modo de depuração. Da mesma forma que o MATLAB, os comandos são executados no shell. Quando você configura um ponto de interrupção em alguma linha de código-fonte, o IDE interrompe a execução e você pode depurar e emitir comandos regulares do IPython.
Parece, no entanto, que a intervenção não funciona (ainda?) (Por exemplo, parar em uma linha e depois entrar em outra função), a menos que você configure outro ponto de interrupção.
Ainda assim, vindo do MATLAB, esta parece a melhor solução que encontrei.
fonte
No python 3.2, você tem o
interact
comando, que fornece acesso ao espaço de comando completo do python / ipython.fonte
Executar a partir do IPython-shell e do ponto de interrupção do Emacs, via pdb.set_trace (), deve funcionar.
Verificado com python-mode.el, Mx ipython RET etc.
fonte
Desenvolvendo novo código
Depurando dentro do IPython
Exemplo de célula:
Depurando código existente
IPython dentro da depuração
pytest ... --pdbcls=IPython.terminal.debugger:TerminalPdb --pdb
breakpoint()
,python -m ipdb
, etc.Pensamentos sobre Python
Concordo com o OP de que muitas coisas que o MATLAB faz muito bem, o Python ainda não tem e realmente deveria, uma vez que praticamente tudo na linguagem favorece a velocidade do desenvolvimento em detrimento da velocidade da produção. Talvez um dia eu contribua com mais do que correções triviais para o CPython.
https://github.com/ipython/ipython/commit/f042f3fea7560afcb518a1940daa46a72fbcfa68
Consulte também É possível executar comandos no IPython com depuração?
fonte