Eu tenho esse aplicativo Python que fica preso de tempos em tempos e não consigo descobrir onde.
Existe alguma maneira de sinalizar para o intérprete Python mostrar o código exato que está sendo executado?
Algum tipo de rastreamento de pilha on-the-fly?
Perguntas relacionadas:
Respostas:
Eu tenho um módulo que eu uso para situações como esta - em que um processo fica em execução por um longo tempo, mas às vezes fica preso por razões desconhecidas e improdutivas. É um pouco hacky, e só funciona em unix (requer sinais):
Para usar, basta chamar a função listen () em algum momento quando o programa iniciar (você pode até colocá-lo no site.py para que todos os programas python o usem) e deixá-lo executar. A qualquer momento, envie ao processo um sinal SIGUSR1, usando kill ou em python:
Isso fará com que o programa seja interrompido em um console python no momento em que está, mostrando o rastreamento da pilha e permitindo que você manipule as variáveis. Use control-d (EOF) para continuar executando (observe que você provavelmente interromperá qualquer E / S etc no momento em que sinalizar, para que não seja totalmente não intrusivo.
Eu tenho outro script que faz a mesma coisa, exceto que ele se comunica com o processo em execução através de um pipe (para permitir a depuração de processos em segundo plano, etc.). É um pouco grande para postar aqui, mas eu o adicionei como uma receita de livro de receitas em python .
fonte
faulthandler
módulo (e seu backport encontrado no PyPI) para um manipulador de sinal de nível C que imprima a pilha Python sem exigir que o loop do interpretador seja responsivo.A sugestão para instalar um manipulador de sinal é boa, e eu o uso muito. Por exemplo, o bzr , por padrão, instala um manipulador SIGQUIT que chama
pdb.set_trace()
para soltá-lo imediatamente em um prompt pdb . (Veja a fonte do módulo bzrlib.breakin para obter detalhes exatos.) Com o pdb, você pode não apenas obter o rastreamento da pilha atual, mas também inspecionar variáveis, etc.No entanto, às vezes eu preciso depurar um processo que não tinha a previsão para instalar o manipulador de sinal. No linux, você pode anexar o gdb ao processo e obter um rastreamento de pilha python com algumas macros do gdb. Coloque http://svn.python.org/projects/python/trunk/Misc/gdbinit em e
~/.gdbinit
, em seguida:gdb -p
PID
pystack
Infelizmente, não é totalmente confiável, mas funciona na maioria das vezes.
Finalmente, anexar
strace
geralmente pode lhe dar uma boa idéia do que um processo está fazendo.fonte
python-dbg
). Sem esses símbolos, você não parece obter muitas informações úteis.Unable to locate python frame
para cada comandoQuase sempre estou lidando com vários threads e o thread principal geralmente não está fazendo muito, então o mais interessante é despejar todas as pilhas (o que é mais parecido com o despejo do Java). Aqui está uma implementação baseada neste blog :
fonte
Obter um rastreamento de pilha de um programa python não preparado , executando um python padrão sem símbolos de depuração, pode ser feito com pyrasite . Funcionou como um encanto para mim no Ubuntu Trusty:
(Dica para o @Albert, cuja resposta continha um ponteiro para isso, entre outras ferramentas.)
fonte
dump_stacks.py
estava simplesmenteimport traceback; traceback.print_stack()
traceback -l
fornece uma lista de scripts python predefinidos que você pode usar edump_stacks.py
é um deles. Se você estiver usando o seu próprio (por exemplo, para gravar o rastreamento de pilha em um arquivo), pode ser aconselhável usar um nome diferente.apt-get install gdb python-dbg
(ou equivalente) antes de executar o pyrasite, caso contrário, ele falhará silenciosamente. Caso contrário, funciona como um encanto!Você também pode formatar bem o rastreamento de pilha, consulte os documentos .
Edit : Para simular o comportamento do Java, conforme sugerido por @Douglas Leeder, adicione este:
para o código de inicialização no seu aplicativo. Em seguida, você pode imprimir a pilha enviando
SIGUSR1
para o processo Python em execução.fonte
O módulo traceback possui algumas funções interessantes, entre elas: print_stack:
fonte
import traceback; f = open('/tmp/stack-trace.log', 'w') traceback.print_stack(file=f) f.close()
Você pode experimentar o módulo do manipulador de falhas . Instale-o usando
pip install faulthandler
e adicione:no início do seu programa. Em seguida, envie SIGUSR1 para o seu processo (ex:) para
kill -USR1 42
exibir o retorno do Python de todos os threads na saída padrão. Leia a documentação para obter mais opções (por exemplo, faça login em um arquivo) e outras maneiras de exibir o rastreamento.O módulo agora faz parte do Python 3.3. Para Python 2, consulte http://faulthandler.readthedocs.org/
fonte
O que realmente me ajudou aqui é a dica do spiv (que eu votaria e comentaria se tivesse os pontos de reputação) para obter um rastreamento de pilha de um processo Python não preparado . Exceto que não funcionou até eu modificar o script gdbinit . Assim:
faça o download de http://svn.python.org/projects/python/trunk/Misc/gdbinit e coloque-o em
~/.gdbinit
editá-lo, mudando[editar: não é mais necessário; o arquivo vinculado já possui essa alteração a partir de 14-01-2010]PyEval_EvalFrame
paraPyEval_EvalFrameEx
Anexar gdb:
gdb -p PID
Obtenha o rastreamento da pilha python:
pystack
fonte
No symbol "co" in current context.
Eu adicionaria isso como um comentário à resposta do haridsv , mas não tenho a reputação de fazê-lo:
Alguns de nós ainda estão presos em uma versão do Python anterior a 2.6 (necessária para o Thread.ident), então eu consegui o código trabalhando no Python 2.5 (embora sem o nome do thread sendo exibido) como tal:
fonte
python -dv herscript.py
Isso fará com que o intérprete seja executado no modo de depuração e fornecerá um rastreamento do que o intérprete está fazendo.
Se você deseja depurar interativamente o código, execute-o assim:
python -m pdb herscript.py
Isso diz ao intérprete python para executar seu script com o módulo "pdb", que é o depurador python, se você executá-lo assim, o intérprete será executado no modo interativo, assim como o GDB
fonte
Dê uma olhada no
faulthandler
módulo, novo no Python 3.3. Umfaulthandler
backport para uso no Python 2 está disponível no PyPI.fonte
No Solaris, você pode usar o pstack (1) Nenhuma alteração no código python é necessária. por exemplo.
fonte
pstack
que faz a mesma coisaSe você estiver em um sistema Linux, use a grandiosidade dos
gdb
com extensões de depuração Python (pode ser empython-dbg
oupython-debuginfo
pacote). Também ajuda com aplicativos multithread, aplicativos GUI e módulos C.Execute seu programa com:
Isso instrui
gdb
a preparápython <programname>.py <arguments>
-r
lo e uni-lo.Agora, quando você programa travar, mude para o
gdb
console, pressione Ctr+Ce execute:Veja exemplo de sessão e mais informações aqui e aqui .
fonte
Eu estava procurando por um tempo uma solução para depurar meus threads e a encontrei aqui graças ao haridsv. Eu uso a versão ligeiramente simplificada, empregando o traceback.print_stack ():
Para as minhas necessidades, também filtre os tópicos por nome.
fonte
Vale a pena olhar para o Pydb , "uma versão expandida do depurador Python vagamente baseada no conjunto de comandos gdb". Inclui gerenciadores de sinais que podem cuidar do início do depurador quando um sinal especificado é enviado.
Um projeto Summer of Code de 2006 analisou a adição de recursos de depuração remota ao pydb em um módulo chamado mpdb .
fonte
Eu hackeei alguma ferramenta que se conecta a um processo Python em execução e injeta algum código para obter um shell Python.
Veja aqui: https://github.com/albertz/pydbattach
fonte
pyrasite
funcionou perfeitamente!Isso pode ser feito com excelente py-spy . É um perfilador de amostragem para programas Python , portanto, seu trabalho é se conectar a um processo Python e fazer uma amostra de suas pilhas de chamadas. Portanto,
py-spy dump --pid $SOME_PID
é tudo o que você precisa fazer para despejar pilhas de chamadas de todos os threads no$SOME_PID
processo. Normalmente, ele precisa de privilégios escalados (para ler a memória do processo de destino).Aqui está um exemplo de como ele se parece com um aplicativo Python encadeado.
fonte
O pyringe é um depurador que pode interagir com os processos python em execução, rastrear a pilha de impressão, variáveis etc. sem nenhuma configuração a priori.
Embora eu tenha usado a solução do manipulador de sinal no passado, ainda pode ser difícil reproduzir o problema em determinados ambientes.
fonte
pyrasite
funcionou como um encanto para mim.Não há como conectar-se a um processo python em execução e obter resultados razoáveis. O que faço se os processos travam está conectando e tentando descobrir o que exatamente está acontecendo.
Infelizmente, muitas vezes o strace é o observador que "corrige" as condições da corrida, para que a saída também seja inútil.
fonte
Você pode usar o PuDB , um depurador Python com uma interface de maldições para fazer isso. Basta adicionar
ao seu código e use Ctrl-C quando desejar quebrar. Você pode continuar
c
e interromper novamente várias vezes, se não entender e quiser tentar novamente.fonte
Estou no campo GDB com as extensões python. Siga https://wiki.python.org/moin/DebuggingWithGdb , o que significa
dnf install gdb python-debuginfo
ousudo apt-get install gdb python2.7-dbg
gdb python <pid of running process>
py-bt
Considere também
info threads
ethread apply all py-bt
.fonte
Traceback (most recent call first): Python Exception <class 'gdb.error'> No frame is currently selected.: Error occurred in Python command: No frame is currently selected.
quando executadopy-bt
emgdb
?sudo
. eu também precisava rodargdb pyton <pid>
como sudo.Como depurar qualquer função no console :
Crie a função em que você usa pdb.set_trace () e , em seguida, a função que deseja depurar.
Em seguida, chame a função criada:
Feliz depuração :)
fonte
Não conheço nada parecido com a resposta do java ao SIGQUIT ; portanto, talvez seja necessário incorporá- lo ao seu aplicativo. Talvez você possa criar um servidor em outro segmento que possa obter um rastreamento de pilha em resposta a algum tipo de mensagem?
fonte
use o módulo de inspeção.
pilha (contexto = 1) Retorna uma lista de registros para a pilha acima do quadro do chamador.
Acho muito útil mesmo.
fonte
No Python 3, o pdb instalará automaticamente um manipulador de sinal na primeira vez que você usar c (ont (inue)) no depurador. Pressionar Control-C depois o levará de volta para lá. No Python 2, aqui está um one-liner que deve funcionar mesmo em versões relativamente antigas (testado em 2.7, mas eu verifiquei o código do Python de volta para 2.4 e parecia bom):
Vale a pena aprender pdb se você gastar algum tempo depurando o Python. A interface é um pouco obtusa, mas deve ser familiar para quem já usou ferramentas semelhantes, como o gdb.
fonte
Caso você precise fazer isso com o uWSGI, ele possui o Python Tracebacker embutido e é apenas uma questão de habilitá-lo na configuração (o número é anexado ao nome de cada trabalhador):
Depois de fazer isso, você pode imprimir o backtrace simplesmente conectando ao soquete:
fonte
No ponto em que o código é executado, você pode inserir esse pequeno trecho para ver um rastreamento de pilha impresso bem formatado. Ele pressupõe que você tenha uma pasta chamada
logs
no diretório raiz do seu projeto.fonte