How to Force Finish a Thread in Python?

Asked

Viewed 526 times

7

How to force a Thread to terminate in Python?

Example:

import threading


def funcao():
    print("Função executando em tarefa paralela.")
    print("Função executando em tarefa paralela.")
    print("Existem outras threads dela mas só essa tem que ser finalizada")
    print("Não vai ficar nenhum laço de repetição aqui checando condição para poder finalizar ela não, a finalização precisa ser forçada de fora")


threading.Thread(target=funcao).start()

I need to force her to finish without using tricks like Return, break, raise, daemom, etc within the function that expects something to be able to finish it. But something outside that function that forces you to end

  • Ah, you want to abort the thread? Like, leave everything in an inconsistent state and just walk away from it? Good luck! :)

  • 1

    @Marcelouchimura can make a little more constructive comment and tell us why this is a bad idea, and what problems can bring? (:

  • Only those who can know what the state of the thread is the thread’s own execution flow. Any attempt to kill him out of context is the same thing as trying to take down a plane out of it.

  • I need to finish a thread from a pre-configured timeout-free socket client to connect. The client is SSL. But sometimes the user inserts a non-SIP IP so the program claws at wrap_socket and by not having timeout pre configured remains Garrated for quite a while. The user can see that.

  • I solved the problem. I put a 30-second timeout until connecting to the server, and once connected I removed the timeout on I/O and the loop loop can finish the thread when you want.

1 answer

2

You can use the asyncio, in which coroutines/tasks (Task) are similar to threads but are not really threads as defined by the OS, and so have no problem changing context or state outside of their own program.

Suppose you want to square a list of numbers from 0 to 4, but want to cancel the 2 2 calculation if the result of some other function is 9, without having inside the corotine of calculation no check, as you requested.

I would do so with asyncio:

import asyncio
import random

# Função que simula algum trabalho de cada tarefa/corotina (semelhante a uma thread)
async def retornar_quadrado(n):
    if n == 2:
        await asyncio.sleep(10)  # A função que será cancelada demora mais.
    else:
        await asyncio.sleep(random.uniform(0.5, 2))  # As outras demoram de 0.5 a 2 segundos.
    return n ** 2


async def main():

    # Criar uma lista de tarefas
    tarefas = []
    for i in range(5):
        tarefa = asyncio.ensure_future(retornar_quadrado(i))
        tarefas.append(tarefa)

    for tarefa_completa in asyncio.as_completed(tarefas):
        try:
            n_quadrado = await tarefa_completa
            print(n_quadrado)
        except asyncio.CancelledError:
            continue

        # Se descobrimos que uma das respostas é 9, cancelamos tarefas[2]
        if n_quadrado == 9 and not tarefas[2].cancelled():
            print('Cancelando tarefas[2]...')
            tarefas[2].cancel()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

An example of a result:

16
9
Cancelando tarefas[2]...
0
1

As you can see, as soon as we found 9, we canceled the calculation of 2 2 and it was never displayed. Removing the line tarefas[2].cancel(), you will see that the result 4 will be displayed, and also that the function will take the 10 seconds that this special case requires.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.