One solution to your problem is to use the module asyncio
.
asyncio
is a library for writing concurrent asynchronous code using syntax async/await
.
asyncio
operates on corroding which are a more generalized form of subroutines. Subroutines have input started at one point, and output at another point. Corroding can enter, exit, and continue at many different points and corroding are declared with the syntax async/await
.
Perform a corroding with:
asyncio.run()
executes and returns the result of corroutine.
asyncio.create_task()
agenda and implementation of a corroding involves her in a Task returning him.
wait
awaiting the return of a corroding. Can only be used inside another corrosion.
As an example two will be created corroding:
demorada()
which is a corrosion that may or may not carry 10s to be executed, is a random choice decided on the line await asyncio.sleep(random.choice((0,10)))
holding or not the processing by 10s. Returns a random number in the range [0,65536[
.
main(timeout=1)
is top-level corrosion. Creates an activity for corrosion demorada()
and is on hold with timeout through the method asyncio.wait_for(aw, timeout)
making an exception asyncio.TimeoutError
if the running time of the activity lasts longer than timeout.
Example:
import asyncio
import random
async def demorada():
await asyncio.sleep(random.choice((0,10))) #Aleatoriamente sorteia se demora ou não 10s
return random.randint(0, 65536) #Retorna no internalo [0,65536[
async def main(timeout=1):
task = asyncio.create_task(demorada()) #Agenda a corrotina demorada() e retorna um task.
try:
await asyncio.wait_for(task, timeout) #Aguarda a execução da Task com timeout.
except asyncio.TimeoutError:
task.cancel() #Cancela a atividade.
print("A função demorou demais para responder.") #Imprime a mensagem.
else:
print(f"A função retornou {task.result()}") #Imprime a mensagem com resultado de demorada()
#Faz 10 chamadas de main() com timeout 5s
for _ in range(10):
print(">>> ",end="", flush="True")
asyncio.run(main(5))
Resulting:
>>> A função retornou 43258
>>> A função demorou demais para responder.
>>> A função retornou 14525
>>> A função retornou 6355
>>> A função demorou demais para responder.
>>> A função retornou 39265
>>> A função demorou demais para responder.
>>> A função retornou 39502
>>> A função demorou demais para responder.
>>> A função retornou 50657
Applying this information to the example of the question just create a loop around the activity and reiterate case of timeout or check its result in a timely manner.
import asyncio
import random
async def demorada():
await asyncio.sleep(random.randint(0,10))
return random.randint(0, 65536)
async def main(timeout=1):
#Abre um loop de duração indeterminada...
while True:
task = asyncio.create_task(demorada()) #Agenda a execução da atividade demorada
print('Fazendo uma tentativa...') #Imprime mensagem
#Abre um bloco de tratamento de exceções...
try:
await asyncio.wait_for(task, timeout) #Aguarda a execução da Task com timeout.
except asyncio.TimeoutError: #Havendo exceção de timeout...
task.cancel() #Cancela a atividade.
print('Time out...') #Imprime mensagem permanecendo no loop.
else:
return task.result() #Retorna o resultado da atividade.
req = asyncio.run(main(5))
print(f'Resultado da chamada {req}')
Resulting:
Fazendo uma tentativa...
Time out...
Fazendo uma tentativa...
Time out...
Fazendo uma tentativa...
Resultado da chamada 20864
Marcio, I marked as duplicate a question where I answered how to implement the timeout. If you have any questions or you feel the answer is of no use to you, please let me know.
– Woss
@Woss improved the question, because only 'kill' the command does not help me, I need it to be re-examined.
– Márcio Mocellin
Just place your/except inside a loop
– Woss