lenguaje - python wikipedia
Función de tiempo de espera si tarda demasiado en terminar (2)
El proceso para agotar el tiempo de una operación se describe en la documentación de la signal .
La idea básica es usar manejadores de señal para configurar una alarma durante un intervalo de tiempo y generar una excepción una vez que el temporizador expire.
Tenga en cuenta que esto solo funcionará en UNIX.
Aquí hay una implementación que crea un decorador (guarde el siguiente código como timeout.py
).
from functools import wraps
import errno
import os
import signal
class TimeoutError(Exception):
pass
def timeout(seconds=10, error_message=os.strerror(errno.ETIME)):
def decorator(func):
def _handle_timeout(signum, frame):
raise TimeoutError(error_message)
def wrapper(*args, **kwargs):
signal.signal(signal.SIGALRM, _handle_timeout)
signal.alarm(seconds)
try:
result = func(*args, **kwargs)
finally:
signal.alarm(0)
return result
return wraps(func)(wrapper)
return decorator
Esto crea un decorador llamado @timeout
que se puede aplicar a cualquier función de larga ejecución.
Entonces, en el código de su aplicación, puede usar el decorador de la siguiente manera:
from timeout import timeout
# Timeout a long running function with the default expiry of 10 seconds.
@timeout
def long_running_function1():
...
# Timeout after 5 seconds
@timeout(5)
def long_running_function2():
...
# Timeout after 30 seconds, with the error "Connection timed out"
@timeout(30, os.strerror(errno.ETIMEDOUT))
def long_running_function3():
...
Esta pregunta ya tiene una respuesta aquí:
- Tiempo de espera en una llamada de función 11 respuestas
Tengo un script de shell que recorre un archivo de texto que contiene URLs que quiero visitar y tomar capturas de pantalla de.
Todo esto está hecho y simple. El script inicializa una clase que cuando se ejecuta crea una captura de pantalla de cada sitio en la lista. Algunos sitios tardan mucho, mucho tiempo en cargarse, y algunos pueden no cargarse en absoluto. Así que quiero envolver la función screengrabber en un script de tiempo de espera, haciendo que la función devuelva False
si no puede terminar dentro de 10 segundos.
Estoy contento con la solución más simple posible, tal vez estableciendo un temporizador asincrónico que devolverá False después de 10 segundos sin importar lo que realmente sucede dentro de la función.
Reescribí la respuesta de David usando la declaración with
, te permite hacer esto:
with timeout(seconds=3):
time.sleep(4)
Lo cual generará un TimeoutError.
El código sigue usando signal
y, por lo tanto, solo UNIX:
import signal
class timeout:
def __init__(self, seconds=1, error_message=''Timeout''):
self.seconds = seconds
self.error_message = error_message
def handle_timeout(self, signum, frame):
raise TimeoutError(self.error_message)
def __enter__(self):
signal.signal(signal.SIGALRM, self.handle_timeout)
signal.alarm(self.seconds)
def __exit__(self, type, value, traceback):
signal.alarm(0)