Se eu tiver um thread em um loop infinito, há uma maneira de encerrá-lo quando o programa principal terminar (por exemplo, quando pressiono Ctrl+ C)?
Respostas:
Verifique esta questão. A resposta correta tem uma ótima explicação sobre como encerrar threads da maneira certa: Existe alguma maneira de eliminar um Thread em Python?
Para fazer o thread parar no sinal de interrupção de teclado (ctrl + c), você pode capturar a exceção "KeyboardInterrupt" e limpar antes de sair. Como isso:
try:
start_thread()
except (KeyboardInterrupt, SystemExit):
cleanup_stop_thread()
sys.exit()
Desta forma, você pode controlar o que fazer sempre que o programa for encerrado abruptamente.
Você também pode usar o módulo de sinal integrado que permite configurar manipuladores de sinal (no seu caso específico, o sinal SIGINT): http://docs.python.org/library/signal.html
cleanup_stop_thread()
uma função global que posso usar? ou devo implementá-lo?
Se você criar threads daemon de threads de trabalho, elas morrerão quando todas as threads não-daemon (por exemplo, a thread principal) forem encerradas.
http://docs.python.org/library/threading.html#threading.Thread.daemon
isDaemon()
é False, defina-o como True por setDaemon(True)
.
isDaemon()
e setDaemon()
são getters / setters antigos (conforme o documento vinculado acima), basta usar daemon=True
inthreading.Thread()
Tente habilitar o sub-thread como daemon-thread.
Recomendado:
from threading import Thread
t = Thread(target=<your-method>)
t.daemon = True # This thread dies when main thread (only non-daemon thread) exits.
t.start()
Na linha:
t = Thread(target=<your-method>, daemon=True).start()
API antiga:
t.setDaemon(True)
t.start()
Quando seu thread principal termina ("isto é, quando eu pressiono Ctrl+ C"), outros threads também serão encerrados pelas instruções acima.
Use o módulo atexit da biblioteca padrão do Python para registrar funções de "término" que são chamadas (no encadeamento principal) em qualquer encerramento razoavelmente "limpo" do encadeamento principal, incluindo uma exceção não capturada como KeyboardInterrupt
. Essas funções de encerramento podem (embora inevitavelmente no thread principal!) Chamar qualquer stop
função que você precisar; junto com a possibilidade de definir um thread como daemon
, que lhe dá as ferramentas para projetar adequadamente a funcionalidade do sistema que você precisa.
atexit.register()
chamadas posteriores aos módulos Python, fazendo com que seu procedimento de encerramento seja executado após o multiprocessing
de um. Eu corro neste problema lidando com Queue
e daemon
threads: “EOF error” na saída do programa usando multiprocessing Queue and Thread .
atexit
manipuladores não são chamados quando threads não daemon estão ativos e a thread principal sai. Consulte Script travado na saída ao usar atexit para encerrar threads .
Se você gerar um Thread como este - myThread = Thread(target = function)
- e então o faça myThread.start(); myThread.join()
. Quando CTRL-C é iniciado, o thread principal não sai porque está aguardando aquela myThread.join()
chamada de bloqueio . Para corrigir isso, basta colocar um tempo limite na chamada .join (). O tempo limite pode ser tão longo quanto você desejar. Se você quiser esperar indefinidamente, coloque um tempo limite realmente longo, como 99999. Também é uma boa prática fazer myThread.daemon = True
para que todos os threads saiam quando o thread principal (não-daemon) for encerrado.
myThread.daemon = True
é uma solução maravilhosa para este problema.
.daemon=True
não é uma solução sólida. Verifique este tópico para obter uma explicação: stackoverflow.com/a/20598791/5562492
Os threads do daemon são eliminados de maneira desagradável, portanto, as instruções do finalizador não são executadas. Uma possível solução é verificar se o thread principal está ativo em vez de um loop infinito.
Por exemplo, para Python 3:
while threading.main_thread().isAlive():
do.you.subthread.thing()
gracefully.close.the.thread()
Consulte Verificar se o thread principal ainda está ativo em outro thread .