Anuncios

Bienvenidos sean a este post, hoy veremos como poder adicionar un tiempo de espera (timeout) para una funcion por medio de un proceso.

Anuncios
Anuncios

En los tiempos actuales la mayoria de las librerias, o todas, que poseen funciones para solicitudes o requests en HTTP nos proveen la posibilidad de especificar un tiempo de espera o timeout cuando ejecutamos la solicitud, es decir que despues de unos X segundos, siendo X el timeout, no se completo la solicitud se procede a cancelar toda la operacion y la ejecucion continua desde la proxima instruccion, como no todas las funciones poseen este tipo de caracteristica para poder simular esta conducta debemos usar a un proceso.

Anuncios

Para entender este concepto vamos a usar un ejemplo, para ello primero importaremos los modulos necesarios:

>>> import socket
>>> from multiprocessing import Process, Queue
Anuncios

Lo primero que importaremos sera el modulo completo para realizar conexiones de red por medio de socket, la segunda sera para las clases para Crear un proceso y las comunicaciones entre ellos, de esto hablamos en este post, pero en esta ocasion en lugar de importar el modulo entero solo haremos con dos clases, lo siguiente sera definir la primera funcion:

>>> def resolver(hostname, timeout=5):
...     salida, ip = resolver_host(hostname, timeout)
...     if salida == 0:
...             return ip
...     else:
...             return hostname
... 
>>>
Anuncios

Esta funcion sera para resolver el hostname del equipo devolviendo la ip del equipo el hostname en caso de no poder hacerlo, para ello usaremos dos variables llamadas salida e ip, en ella almacenaremos la salida de la funcion resolver_host (que aun no existe) y despues por medio de un condicional si salida es igual a 0, es decir que fue exitoso, devolveremos el valor de ip de lo contrario devolveremos el nombre del host, pasemos a definir la funcion que no existe:

>>> def resolver_host(hostname, timeout):
...     encola = Queue()
...     proc = Process(target=gethostpornombre,args=(hostname, encola))
...     proc.start()
...     proc.join(timeout=timeout)
...     if encola.empty():
...             proc.terminate()
...             ip = None
...     else:
...             ip = encola.get()
...     return proc.exitcode, ip
... 
>>>
Anuncios
Anuncios

En este caso recibimos los dos datos de la funcion anterior, primero crearemos un objeto para el Queue, luego otro para el proceso que ejecutara una funcion que definiremos a continuacion, comenzamos el proceso y luego terminamos una vez pasado el valor informado en el timeout, despues tenemos un condicional donde chequea si encola esta vacio (empty) y en caso de ser verdadero termina al proceso y asigna el valor None a ip, esto equivale a decir que fallo la resolucion del host, de lo contrario asignaremos el valor en encola a ip, por ultimo devolvemos el valor de salida de codigo del proceso y la direccion ip, sea asignada o no, pasemos a definir la funcion faltante:

>>> def gethostpornombre(hostname, encola):
...     ip = socket.gethostbyname(hostname)
...     encola.put(ip)
... 
>>>
Anuncios

En esta funcion obtendremos la ip del host por medio del nombre del mismo, para ello recibira dos valores que son el nombre del host y el objeto Queue, dentro de esta crearemos una variable llamada ip donde por medio de gethostbyname del modulo socket obtendremos la ip, luego pasaremos por medio de put al objeto Queue, con esto realizado ya tenemos una funcion para verificar como funciona, probemos con el siguiente ejemplo y para ello escribiremos la siguiente linea:

>>> print(resolver('tinchicus.com'))
Anuncios

Como pueden ver simplemente usamos a print para que invoque a resolver y le pasamos un dominio de ejemplo, una vez ejecutado nos devolvera lo siguiente:

>>> print(resolver('tinchicus.com'))
192.0.78.25
>>>
Anuncios

Inclusive si lo probamos con un red de intranet funcionara, siempre que el servidor de DNS funcione correctamente:

>>> print(resolver('intranet.kumaras.local'))
172.128.11.1
>>>
Anuncios

Pero si nosotros informamos un dominio no registrado o inexistente sucedera lo siguiente:

>>> print(resolver('dominiodeprueba.net'))
Process Process-12:
Traceback (most recent call last):
  File "/usr/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
    self.run()
  File "/usr/lib/python3.7/multiprocessing/process.py", line 99, in run
    self._target(*self._args, **self._kwargs)
  File "<stdin>", line 2, in gethostpornombre
socket.gaierror: [Errno -2] Name or service not known
dominiodeprueba.net
>>>
Anuncios

A pesar de devolvernos un error si nos termina devolviendo el dominio en lugar de la direccion ip pero tambien sucede que se finalizo al proceso en el camino, en realidad con las conexiones actuales es muy dificil ver como podemos tener un timeout debido a la falla de conexion pero siempre puede ocurrir y nuestro codigo lo tiene contemplado.

Anuncios

En resumen, hoy hemos visto como crear un tiempo de espera o timeout para funciones que carecen del mismo, en este caso lo aplicaremos por medio de un proceso, tambien hemos visto como obtener las direcciones ip de equipos registrados en el DNS que nos conectemos, ya sea de internet como de intranet, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Donación

Es para mantenimento del sitio, gracias!

$1.50