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):
import code, traceback, signal
def debug(sig, frame):
"""Interrupt running process, and provide a python prompt for
interactive debugging."""
d={'_frame':frame} # Allow access to frame object.
d.update(frame.f_globals) # Unless shadowed by global
d.update(frame.f_locals)
i = code.InteractiveConsole(d)
message = "Signal received : entering python shell.\nTraceback:\n"
message += ''.join(traceback.format_stack(frame))
i.interact(message)
def listen():
signal.signal(signal.SIGUSR1, debug) # Register handler
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:
os.kill(pid, signal.SIGUSR1)
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 .