Los sockets en Python.

logo python

Es común, incluso puede ser habitual, que necesitemos crear una conexión entre dos programas o dispositivos al programar; pues bien, los sockets en Python y otros lenguajes, están pensados para eso. 

Los sockets son una estructura que permite la conexión entre dos aplicaciones, procesos o equipos, (IPC) estableciendo una relación cliente/servidor, que permite el intercambio de datos, incluso entre programas colocados en ordenadores diferentes.

Los sockets, pueden interpretarse como el punto final de una conexión, donde para establecerla será necesario como mínimo:

  • definir la dirección IP local y remota de los ordenadores que participan,
  • el puerto de conexión
  • y el protocolo de transporte de la información.  

La comunicación que se crea tendrá por tanto un carácter bidireccional.

La relación cliente/servidor, también significa que el comportamiento de los socket no es el mismo, en ambos casos, mientras en el cliente es el punto final de una conexión, en el servidor se comporta como una centralita telefónica, que usa sockets clientes y servidor

La fácil manipulación que ofrecen los sockets, los hace prácticamente imprescindibles, si la conexión es multiplataforma, aunque también son ampliamente usados en cualquier tipo de comunicación IPC (Inter-Process Communication), sin que sean los únicos, que existen.

Los tipos de sockets en Python:

Pueden ser de flujo (sock Stream), que emplean el protocolo  de transmisión TCP, o de datagrama (Sock_Dgram), que emplean UDP, para transmitir los datos.

El protocolo TCP (Transmission Control Protocol), difiere  en muchos elementos de UDP( User Datagram Protocol), sin embargo la forma más simplificada de explicar su diferencia, seria decir que los mensajes enviados por TCP llegan a su destino en el mismo orden en que se enviaron y los que se envían por UDP, pueden llegar en un orden diferente a como fueron enviado originalmente, además de que en el segundo no hay una forma de verificar la entrega y que es TCP, quien incorpora el concepto de puerto.

En Python, para expresar los datos de conexión para la familia de direcciones AF_INET, se emplea una lista con dos parámetros (host, puerto).

Donde host es una cadena que representa un nombre de host en notación de dominio de Internet como ‘darling.com ‘ o una dirección IPv4 como ‘100.50.200.50’, y el puerto es un entero.

Crear un socket en Python

Los sockets bajo el método TCP, son una forma común de comunicación en internet, por ejemplo, al interactuar con un navegador.

Cuando se da click sobre una dirección en el buscador, es como si escribiéramos lo siguiente en un socket cliente:

sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.connect(("www.mi_pagina", 80))

En este código primero creamos un objeto socket, que es del tipo cliente, al cual pasamos dos argumentos: el tipo de familia de direcciones (AF_INET), y el tipo de socket (sock-stream).

Clarificando un poco esto, aclaro que existen muchas familias de direcciones (F_UNIX, AF_INET6, AF_NETLINK, AF_TIPC, AF_CAN, AF_BLUETOOTH, AF_PACKET, AF_RDS), siendo AF_INET, la más común.
AF significa Address Family. AF_INET que bien pudo llamarse AF_INET4, se refiere a la familia de direcciones del tipo Protocolo de Internet v4 (IPv4), que emplean 32 bits, mientras AF_INET6 se refiere a familia de direccionamiento de IPv6, que utiliza 128 bits.

Volviendo al código, si bien este sería el script en el socket cliente; en el socket servidor ocurre algo más:

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((socket.gethostname(), 2222))
serversocket.listen(4)

O sea, creamos un objeto con las mismas propiedades del cliente, sin embargo empleamos bin(), para vincularlo a un hostname y un puerto; y finalmente ponerlo a escuchar.

Viendo el detalle; en el primer parámetro de bin(), estamos indicando a que dirección se conectará.

Usamos gethostname() en este caso, para que tome un host visible en la red, fuera de nuestro ordenador, pero podríamos emplear localhost, o 127.0.01, para que se visible solo en nuestra máquina.

Los puertos de socket, el segundo parámetro de bin(), suelen ser puertos con valores de 4 dígitos.

listen(), le indica a la librería del socket la cantidad de solicitudes máximas de conexión que deseamos poner en cola. Hemos escogido 4, que un número aceptable.

Aunque de forma general, esto es lo que ocurre al establecerse una comunicación entre sockets, que será mejor mostrarlo en un ejemplo más amplio, donde abarquemos todos los momentos.

En este ejemplo emplearemos sys(), para atrapar los errores desde el intérprete, que se produzcan en la salida en la salida del código.

SOCKET SERVIDOR

#importamos las librerias
import socket
import sys

# creamos el objeto socket 
objetoSocket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

#introducimos en una variable los datos del servidor
datos_servidor = ('localhost', 10000)
# empleamos sys.stderr para imprimir
print >>sys.stderr, 'empezando a levantar %s puerto %s' % datos_servidor

# asociamos el socket con la dirección del servidor, empleando bind() 
objetoSocket_server.bind(datos_servidor)
# para que nuestro socket sea capaz de aceptar la conexión entrante desde el cliente
# y pueda escuchar el mensaje utilizaremos dos métodos: el método accept()
# que nos devuelve una conexión abierta entre el servidor y el cliente, 
# por la cual los datos, se leen y transmiten mediante recv() y sendall() 
# respectivamente y el metodo listen(), que nos indica las cantidad maxima de 
# conexiones aceptadas

objetoSocket_server.listen(1)
while True:
     print >>sys.stderr, 'Esperando para realizar conexión'
     connection, datos_cliente = objetoSocket_server.accept()

# manejamos la conexion
try:
     print >>sys.stderr, 'conectando desde', datos_cliente
     
     while True:
          data = connection.recv(19)
          print >>sys.stderr, 'recibido "%s"' % data
          if data:
               print >>sys.stderr, 'devolviendo mensaje al cliente'
               connection.sendall(data)
          else:
               print >>sys.stderr, 'no hay mas datos', datos_cliente
               break
finally:
     connection.close()

SOCKET CLIENTE

# importamos las librerias
import socket
import sys
#creamos el objeto socket
objetoSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM 

# creamos una variable con los datos del servidor.
datos_servidor = ('localhost', 10000)
# empleamos sys.stderr para imprimir
print >>sys.stderr, 'conectando a %s puerto %s' % datos_servidor

#conectamos
objetoSocket.connect(datos_servidor)
try:
     mensaje = 'Mensaje de prueba'
     print >>sys.stderr, 'enviando "%s"' % mensaje
     '''
     empleamos sendall()para enviar la información y recv(), para   recibirla,
     los parámetros del método sendall son los datos que se van a enviar, y el 
     parámetro de la funcion  recv()m es el número máximo de bytes a aceptar.
     '''
     objetoSocket.sendall(mensaje) # enviando el mensaje
     cantidad_recibida = 0
     cantidad_esperada = len(mensaje) # recibiendo la respuesta
 
     while cantidad_recibida < cantidad_esperada: data = objetoSocket.recv(19) cantidad_recibida += len(data) print >>sys.stderr, 'recibiendo "%s"' % data

    # cerramos  el socket al concluir con el método close().
    finally:
        print >>sys.stderr, 'cerrando socket'
        objetoSocket.close()

Como un último punto en este ejemplo, es bueno añadir que el socket cliente es normalmente usado, solo para un intercambio (o un pequeño número de comunicación secuencial), de modo que una vez terminado connect() es destruido

En esencia, esta es la estructura de una conexión IPC, empleando sockets.

El concepto de los sockets en Python

Resumiendo lo visto hasta aquí, la comunicación del tipo IPC, se ejecuta mejor empleando sockets, los cuales funcionan bajo la estructura cliente servidor.

El socket cliente  tiene como función básica conectarse y solicitar o envíar información, mientras  la labor del socket servidor es crear sockets clientes y escuchar el puerto.

Dicho de otro modo: una vez creado el socket servidor, este crea un par de sockets clientes, desde los que escucha la información.

La función del socket servidor , no es mandar ningún dato o recibirlo ; sino que produce sockets clientes y cada uno de estos es creado en respuesta a algún otro socket cliente que hace connect() al host y al puerto al que el socket servidor está vinculado.

Tan pronto como el servidor crea ese socket cliente, vuelve a escuchar por más conexiones.

Los dos sockets clientes, pueden conversar entre ellos, usando un puerto asignado dinámicamente y que será reciclado cuando la conversación termine.

Más sobre los sockets en Python

Existen alternativas para manipular la conexión de manera mas efectiva; ya que una vez creada  la conexión, el bucle que empleamos anteriormente, puede funcionar de diferentes modos:

  • Crear un hilo para manejar clientsocket,
  • crear un proceso nuevo para manejar clientsocket 
  • Reestructurar el codigo para usar sockets no bloqueantes y usar select para  multiplexar entre el «socket servidor» y cualquier clientsocket  activo.

IPC

Para ejecutar conexiones IPC rápidas entre dos procesos en una misma máquina, lo aconsejable es revisar la memoria compartida o las tuberías (PIPES).

Cuando se usan  sockets  con el tipo de redirección AF_INET, es una opción aconsejable vincular el servidor  con «localhost», ya que provee un atajo alrededor de algunas capas del código de red, que funciona en casi todas las plataformas.

Los verbos send y recv

Los verbos send y recv operan en los buffers de red y están enfocados a manejarlos; y debido a ello, no  están obligados a manejar obligatoriamente, todos los bytes que se les entrega, o se espera qué entreguen.

Esto crea la necesidad de llamarlos nuevamente hasta que el mensaje haya sido tratado por completo.

Como devuelven resultados cuando el buffer se llenado (send) o vaciado(recv); cuando recv() retorna 0 bytes es porque al otro lado se ha cerrado , o está en el proceso de cerrar la conexión y si ya hemos dicho que se recicla después del close(), entonces no recibirás  datos de esta conexión, nunca más.

Si la conexión no se ha interrumpido, nuestro recv() podría esperar eternamente, porque el socket no dirá, cuando no hay más nada por leer.

Por tanto, otra practica a tener en cuenta es saber qué hacer con el limite de la conexión, cerrarla, darle una longitud fija o delimitarla; pero, no hablaré en este articulo -que ya se ha hecho muy largo- de este tema.

Cerrar los sockets

Para Python cuando un socket es eliminado por el recolector de basura, automáticamente llama a close().

Esto elimina la posibilidad de que quede eternamente abierto, aunque confiar en esto es una mala práctica, porque puede no evitar que el socket del otro lado espere indefinidamente, pensando que su pareja solo esta siendo lenta y TCP es un protocolo confiable, que esperará un largo tiempo antes de rendirse con una conexión.

Por ello, lo recomendado es llamar a close(), siempre y cuando no estes usando hilos.

Sockets bloqueantes y no bloqueantes.

Todo lo que hemos visto hasta aquí, es el procedimiento  para un socket bloqueante

En Python,  se usa socket.setblocking(False) para que un socket no sea bloqueante.

Se diferencia en que send()recv()connect() y accept() pueden retornar sin haber hecho nada.

Debido a ello, se necesita leer  el retorno de un modo óptimo. Un buena solución es emplearse la función select()

Usando select.

ready_to_read, ready_to_write, in_error = \
               select.select(
                  potential_readers,
                  potential_writers,
                  potential_errs,
                  timeout)

select() se le pasan tres listas: la primera con todos los sockets que puede intentar leer; la segunda con todos los sockets que puede intentar escribir, y la tercera, qué usualmente se deja vacía, incluye a aquellos a los que se quiera verificar los errores.

Teniendo en cuenta su complejidad, es muy probable que necesites colocar un socket en más de una lista.

Aunque la llamada a select(), se comporta como bloqueante, acepta darle un tiempo de espera largo.

El retorno de la función devuelve igualmente tres listas, que contienen los sockets que son realmente legibles, escribibles y con error. Cada una de estas listas es un subconjunto (posiblemente vacío) de la lista correspondiente que se pasó a select().

Cuando un socket está en la lista retornada legible, eso significa que una llamada a recv() en este socket va a retornar algo, y lo mismo para la lista de escribibles, ese socket será capaz de mandar algo  y eso solo significa que el espacio de salida del buffer de red está disponible.

En caso de que se necesite revisar a un socket servidor, debe ir en la lista de potenciales legibles y si retorna como legible es casi seguro que una llamada a accept() va a funcionar.

Si se posee un nuevo socket para llamar a connect() y conectarlo con otro, debe ir en la lista de potenciales escribibles,  y si retorna como escribible, es que seguramente esta conectado.

select() puede ser útil incluso con sockets bloqueantes, ya que  el socket retorna como leíble cuando hay algo en el buffer, no obstnte vale aclarar que esto no sirve de ayuda con el problema de determinar si el  socket al otro lado culminó la conexión, o solo está ocupado.

Y hasta aquí, espero modestamente, que esto sirva de ayuda a alguien.

Tres cosas necesitan las ovejas para andar en manada, el miedo al perro, la voz de amo y que la de atrás empuje, por miedo a quedarse sola.

Y.

Crear un mapa con Folium en Python

logo python

En este articulo, mostraré como crear un mapa con Folium en Python, por diferentes vías.

Folium es una librería fantástica, que nos permite crear mapas de un modo simple y ágil y que puede ser una magnifica alternativa a basemap.

La forma básica de crear un mapa en Folium es :

import folium
from folium import plugins
import ipywidgets
import pandas as pd
import numpy as np

folium.Map()#aqui llamamos al mapa simple 

Otra forma simple, es crear el mapa, acotando elemento como el zoom, el área,  la escala  y tamaño del mapa y una dirección especifica. Esta ultima mediante su latitud y longitud.

folium.Map(location=[39.473861, -0.360830], zoom_start=80, width=500, height= 600, control_scale=True)

Otros artículos sobre Python

Esta muestra además la escala y se puede controlar el tamaño del mapa

Controlar el tamaño del mapa

También podemos controlar el tamaño del mapa es empleando  el modulo figure() de la librería branca().

from branca.element import Figure

#folium.Map()
map_1= folium.Map(location=[39.473861, -0.360830], zoom_start=80, control_scale=True)
map_1
fig = Figure(width=1000, height=500)
fig.add_child(map_1)
fig

Guardar el mapa

Para guardar el mapa en folium, basta con darle un ruta al  método save()

Tipos de mapas con widgets

Con folium es fácil añadir widgets a los mapas, que los hacen muy útiles y amplian mucho las posibiidades de visualización.

En el ejemplo mostramos diferentes vistas de un mapa, empleando los widgets:

#seleccion de los widgets
select_widgets=ipywidgets.Select( 
    options=['Open Street Map', 'Terrain', 'Watercolor', 'Positron', 'Dark Mater'],
    value = 'Open Street Map',
    description ='Tipos de mapa:',
    disable= False)
def selectMap(maptype):
    if maptype == "Open Street Map":
        display(folium.Map(location=[39.473861, -0.360830], zoom_start=80, control_scale=True))
    if maptype == "Terrain":
        display(folium.Map(location=[-12.055815, -77.0567980], zoom_start=50, control_scale=True))
    if maptype == "Watercolor":
        display(folium.Map(location=[20.0521337, -75.860336], zoom_start=10, tiles='Stamen Watercolor', control_scale=True))
    if maptype == "Positron":
        display(folium.Map(location=[40.410610, -3.490617], zoom_start=10, tiles='CartoDB Positron', control_scale=True))
    if maptype == "Dark Mater":
        display(folium.Map(location=[40.410610, -3.490617], zoom_start=10, tiles='CartoDB Dark_Matter', control_scale=True))

#interactuando entre el widget y la funcion
ipywidgets.interact(selectMap, maptype=select_widgets)

Hay mucho mas que sacar de Folium, como mapas de calor, así que te invito a investigar esta útil librería y sacarle jugo a sus enormes posibilidades.

Espero que esto sirva de ayuda a alguien. Muchas gracias.

Pocos saben lo mucho que debemos saber, para darnos cuenta de lo poco que sabemos

R. Tagore

El uso de with en Python

logo python

Si has llegado hasta aquí, debe ser porque te interesa que nos facilita el uso de with en Python, al principio de un bloque de código.

Entonces, intentaré no defraudarte y explicártelo de forma sencilla.

with() es lo que se conoce como un manejador de contexto.

Al usar with() Python  lo que hace abstraernos del código repetitivo ya que  corre a cuenta de with  cerrar el fichero  después de ejecutarse el código que se encuentra en el interior del bloque, incluso si ocurre alguna excepción.

Como with() nos facilita las tareas repetitivas su efecto es similar a una bucle del tipo try-finally.

with open('hola.txt', 'r') as f:
for linea in f:
...

Esto equivaldría a algo así:

f = open('hola.txt', 'r')
try:
for linea in f:
...
finally:
f.close()

Y esto es todo.

Espero modestamente ayudar a alguien.

La ignorancia es la muerte de los vivos

D.

Sumar y restar días en Python con datetime.

logo python

Por el uso tan amplio de Python es realmente necesario poder sumar y restar días en Python, y para eso podemos emplear la librería datetime.

En situaciones donde necesitamos llevar un seguimiento de la fecha y la hora, podemos emplear este modulo que es el encargado de de manipular fechas y horas, y está integrado en la biblioteca estándar de Python.

Las clases con las que cuenta el modulo son:

 NOMBREDESCRIPCIÓN
1.fechaMuestra la fecha según el calendario georgiano con atributos como año, mes y día.
2.horaMuestra el tiempo, independientemente de cualquier día en particular, con atributos como hora, minuto, segundo, microsegundo y tzinfo.
3.fecha y horaEs una colección de fecha y hora con los atributos año, mes, día, hora, minuto, segundo, microsegundo y tzinfo.
4.timedeltaSe utiliza para manipular la fecha.
5.tzinfoProporciona información sobre la zona horaria.

Otros post sobre Python

TIMEDELTA  para sumar y restar

Para sumar o restar fecha, usamos la función timedelta() ya que permite realizar operaciones aritméticas con las fecha como sumar o restar y es fácilmente implementable.

La sintaxis es la siguiente

class datetime.timedelta(días = 10, segundos = 40, microsegundos = 10, milisegundos = 60, minutos = 10, horas = 4, semanas = 8)

Nota: si no especificamos por defecto, toma el entero como un día. 

Sumar 10 días 

from datetime import date, timedelta
 
hoy = date.today()
 
print("hoy es : ", hoy)
 
td = timedelta(10)
print("Dentro de 10 diás estaremos a : ", hoy + td)

Restar 1 día 

from datetime import date, timedelta
 
hoy = date.today()
 
print("hoy es : ",hoy)
 
print("ayer fue : ",ayer - timedelta(1))

Sumar tiempos específicos

from datetime import datetime, timedelta
 
ahora = datetime.now()
print("Current Date and time :- ", curr)
 
nuevo = timedelta(days = 10, seconds = 40, 
                         microseconds = 10,
                         milliseconds = 60, 
                         minutes = 10, hours = 4,
                         weeks = 8)
 
print("nuevo tiempo calculado :- ", nuevo + new_datetime)
from datetime import datetime, timedelta
  
  
ahora = datetime.now()
  
# printing initial_date
print ("fecha inicio", str(ahora))
  
# Calculamos fechas futuras
en_dos_anos = ahora + \
                        timedelta(days = 730)
  
en_dos_dias = ahora + \
                         timedelta(year = 2)
  

print('en dos años estaresmos a:', str(en_dos_anos))
print('en dos dias será:', str(en_dos_dias))

Y hasta aquí, espero sinceramente que este articulo sirva de ayuda a alguien.

Y todo como el diamante antes que luz, fue carbón.

J. Martí

Como recorrer directorios en Python con scandir

logo python

En este post aprenderás como recorrer  directorios en Python con scandir.

La documentación actualizada de Python recomienda recorrer directorios en Python con scandir como método.

Scandir es un método del DirEntry que pertenece a la libreria Os, dicho de otro modo  os.scandir, se usa para crear un iterador de los objetos del  método os.DirEntry correspondientes a los  elementos que existan en el argumento path.

Su sintaxis es:

 scandir(‘path’)

El objeto que crea scandir() expone la ruta y otros atributos del archivo en el directorio.

Este método proporciona toda la información posible sobre el directorio de una sola vez, lo que evita llamadas adicionales l sistema información como sea posible sin realizar llamadas al sistema adicionales.

Las instancias de os.DirEntry, entre las que se encuentra scandir no almacena sus resultados en estructuras de datos de larga duración; por tanto es recomendable llamar al método de scandir stat, con la sintaxis  os.stat(entry.path), si se necesita actualizar la información y este resultado se almacena en caché al igual que si se llama a lstat()

Este método genera excepciones del tipo OSError, que puede ser manejado como cualquier otro método en Python.

Otros artículos sobre Python

Veamos varios ejemplos de uso scandir().

# importmos os 
import os

 
# Directorio que nos interesa recorrer 
path = '/home/soluciones'
 
# Scaneamos el  directorio y creamos un iterador de  los objetos de tipo os.DirEntry 

directorio = os.scandir(path)
 
# Listamos todos los archivos y directorios dentro de esa ruta 
print("Archivos y  Directorios in '% s':" % path)
for cosas  in directorio :
    if cosas.is_dir() or cosas.is_file():
        print(entry.name)
 
 
# cosas.is_file() chequea si los elementos existentes son archivos o no
# cosas.is_dir() chequea si los elementos existentes son directorios o no
 
# para cerrar el iterador podemos llamar scandir.close(), no obstante este método
# es llamado de modo automatico cuando el iterador excede su capacidad o cuando
#ocurre un error al iterar
directorio.close()
 

En el siguiente ejemplo además de determinar si existe el objeto, definiremos con qué comienza o termina el nombre.

import os
dir = "/Users/blackmaster/Downloads/"
textos=[]
directorios_p=[]
with os.scandir(dir) as contenido:
    for cosas in contenido:
        #si cosas es archivo y termina en .csv lo añadimos a la varible textos
        if cosas.is_file and cosas.name.endswith('.csv'):
            textos.append(entry.name)
        #si cosas es directorio y comienza con p lo añadimos a la varible directorios p    
        if cosas.is_dir and cosas.name.startswith('p'):
            directorios_p.append(cosas.name)
            
print(textos)
print(directorios_p)

Y hasta aquí, espero modestamente, que este post ayude a alguien.

Tres cosas necesitan las ovejas para andar en manadas, el miedo al perro, la voz de amo y que la de atrás empuje por miedo a quedarse sola.

Y.

Ejecutar comandos Shell en Python con os.system

logo python

Si en alguna ocasión, ante alguna necesidad de programación, has necesitado ejecutar comandos Shell en Python con os.system, tienes una opción interesante que te mostraré si sigues leyendo.

Python nos permite ejecutar un comando de shell que se almacena en una cadena usando os.system()

import os
#muestra el mensaje en la consola
os.system("echo mostrar mensaje en la consola")
output
mostrar mensaje en la consola

Al igual que os.system() en el ejemplo anterior, donde imprimimos con echo el mensaje en consola, podemos no usar echo y obtener una salida estándar (stdout) que no se muestra en consola.

Cuando damos una orden con os.system, el resultado positivo será igual a 0, o diferente de 0, en caso de que no se cumpla.

En este ejemplo, intentamos mover el directorio actual a un directorio que no existe, por tanto recibimos un error diferente de 0.

directorio_erroneo = os.system("cd directoriofalso")
print("cd directoriofalso da un codigo de error %d" % directorio_erroneo)
Output
sh: line 0: cd: directoriofalso: No such file or directory
cd directoriofalso da un codigo de error 256

Podemos emplear otros métodos más potentes para escribir comandos Shell en Python como subprocess().

Y hasta aquí, espero ayudar a alguien con este post.

Hacer preguntas es prueba de qué se piensa.

R. Tagore

Contar las apariciones de un carácter en una cadena de Python.

logo python

En muchas ocasiones nos hemos o veremos necesitados de contar las  apariciones de un carácter en una cadena de Python, para lo cual tenemos diferente opciones.

En dependencia de nuestra necesidad, o el módulo con el que nos encontremos trabajando, podremos hacerlo por una vía u otra

for

Podemos recorrer la cadena, crear un contador e incrementarlo en uno cada vez que encuentre en carácter que buscamos.

cadena = 'Quien va en busca de montañas, no puede detenerse a recoger las piedras del camino.'
    
contador = 0 
for i in cadena:
    if i == "a":
        contador = contador + 1
print(contador)
salida
8

count

La función count(), devuelve de un modo sencillo, cúantos caracteres  iguales al que e le pasa como parámetro, existen en la cadena.

Sintaxis

array.count('x')

Aquí, dos modos de implementarla:

a = 'Quien va en busca de montañas, no puede detenerse a recoger las piedras del camino.'.count('n')
print(a)
print('Quien va en busca de montañas, no puede detenerse a recoger las piedras del camino.'.count('a'))
salida
6
8

Una función lambda

Una lambda en Python, es la mínima función que se puede expresar dentro de una expresión.

Por tanto para contar caracteres con una función lambda, podemos plantearlo con la función map() que aplicará sobre cada integrante de la lista una acción que en nuestro caso será dar valor 1 y luego lo sumaremos con la función sum().

cadena = 'Quien va en busca de montañas, no puede detenerse a recoger las piedras del camino.'
# utilizamos las funciones map y sum, un bucle if  - else la funcion map y sum, 
# lammbda parametro . accion, donde se ejecuta
print(sum(map(lambda x : 1 if 'a' in x else 0, cadena)))
salida
8

defaultdict

defaultdict(), pertenece al modulo collections. Permite contar los elementos dados dentro de una cadena y devuelve un valor 0 si el carácter no existe.

from collections import defaultdict
cita = 'Quien va en busca de montañas, no puede detenerse a recoger las piedras del camino.'
chars = defaultdict(int) #creamos el objeto con el parámetro int

for char in cita:  #empleamos un for para recorrer la cadena 
    chars[char] += 1
    
print(chars['a'])
print(chars['e'])
print(chars['i'])
print(chars['o'])
print(chars['u'])
print(chars['l'])
print(chars['m'])
print(chars['n'])
print(chars['u'])
print(chars['z']) #caracter que no existe
print(chars['h']) #caracter que no existe
print(chars['v'])

salida
8
13
3
4
3
2
2
6
3
0
0
1

collections.counter

counter() es una subclase de dictado para contar objetos hash, o sea datos estructurados de forma que asocian llaves o claves con valores.

En esta colección, los elementos se almacenan como claves de diccionario y sus recuentos se almacenan como valores de diccionario. El conteo puede arrojar cualquier cualquier valor entero, incluido el cero, o valores negativos. Counter devuelve cero para elementos inexistentes.

cadena = 'Quien va en busca de montañas, no puede detenerse a recoger las piedras del camino.'
from collections import Counter
cadena = 'Quien va en busca de montañas, no puede detenerse a recoger las piedras del camino.'
counter = Counter(cadena)
print(counter['a'])
print(counter['x'])
salida
8
0

Otros artículos sobre Python

pandas.df.value_count

La librería Pandas por supuesto, también ofrece  una funcion simple para contar caracteres en una cadena.

Debemos primero convertir la cadena a un dataframe o serie  pandas y luego aplicarle  la función value.count(), como se ve en el ejemplo:

import pandas as pd
cadena = 'Quien va en busca de montañas, no puede detenerse a recoger las piedras del camino.'
print(pd.Series(list(cadena)).value_counts())
salida
14
e    13
a     8
n     6
s     5
d     5
o     4
r     4
u     3
c     3
i     3
l     2
m     2
p     2
t     2
,     1
v     1
ñ     1
Q     1
g     1
b     1
.     1
dtype: int64

re  y findall trabajando con expresiones regulares

El modulo re y la función findall(), nos permiten trabajar con expresiones regulares. Digamos que una expresión regular, es una sintaxis dada que está contenida en un patrón. Si hacemos coincidir es patrón con nuestro parámetro de búsqueda, obtendremos los elementos que se repiten.

import re
cadena = 'Quien va en busca de montañas, no puede detenerse a recoger las piedras del camino.'
print(len(re.findall("a", cadena))) 

Y hasta aquí, espero sinceramente que esto sirva de ayuda a alguien.

Por mucho tiempo que este un tronco en el agua, nunca llegará a ser cocodrilo.

D.

Copiar un fichero en Python con shutil

logo python

Veamos hoy como copiar un fichero en Python con shutil, que es un modulo que Python ofrece para este tipo de acciones

Tenemos varias opciones, a continuación, te las muestro:

copy

Este es un modulo de Python, que pertenece a shutil().

copy() copia el contenido del fichero y sus permisos, pero sin embargo, no copia los metadatos del fichero.

copy() acepta como parámetros, los siguientes:

  • src: Ruta completa del fichero origen, en formato cadenav(string), o un objeto(PathLike)
  • dst: Ruta del fichero  de destino. En este caso  hay que considerar que si la ruta es un directorio, se copiará el fichero origen en el directorio y tomará como nombre el del fichero original.
  • follow_symlinks (default =True): Cuando follow_symlinks es falso y src es un enlace simbólico, dst se creará como un enlace simbólico. Si follow_symlinks es verdadero y src es un enlace simbólico, dst será una copia del archivo al que se refiere src.
import shutil
shutil.copy('origen.txt', 'destino.txt')
shutil.copy('/ruta/origen.txt', '/ruta/destino/copia.txt')
shutil.copy('/ruta/origen.txt', '/ruta/destino')

Otros artículos sobre Python

copy2

La función copy2(), permite copiar los metadatos del archivo y funciona exactamente igual que copy().

import shutil
shutil.copy2('origen.txt', 'destino.txt')
shutil.copy2('/ruta/origen.txt', '/ruta/destino/copia.txt')
shutil.copy2('/ruta/origen.txt', '/ruta/destino')

Copyfile

copyfile() permite  copiar  solo el contenido de un fichero.

Su sintaxis es:

copyfile(src, dst, follow_symlinks=True). 

Esta función hace una copia del fichero original src() en el fichero destino dst(). Tanto src(), como dst(), son cadenas de texto que ofrecen rutas.

Considera, que si el fichero destino ya existe, este será reemplazado.

La función lanzara un OSError, si no se puede  escribir en el destino.

import shutil
shutil.copyfile('origen.txt', 'destino.txt')
shutil.copyfile('/ruta/origen.txt', '/ruta/destino/copia.txt')

Copyfileobj

Esta función funciona como  copyfile(), con la diferencia  de que src() y dst() deben ser objetos de tipo fichero (no  un string con las rutas).

import shutil
file_src = 'source.txt' 
f_src = open(file_src, 'rb')
file_dest = 'destination.txt' 
f_dest = open(file_dest, 'wb')
shutil.copyfileobj(f_src, f_dest)

Y hasta aquí, esto es todo.

Espero que sirva de ayuda a alguien

Para ser parte del 1%, hay que hacer lo que el 99% no hace.

D.

Cambiar el tamaño de la imagen en Python con opencv

logo python

En este pequeño post enseñaré como cambiar el tamaño de una imagen en Python con opencv. Python es un lenguaje que resulta útil, para llevar a cabo muchas tareas necesarias, incluido el tratamiento de imágenes, que pueden exigir diferentes niveles de complejidad.

Consideremos primero que una  imagen es un array, que puede ser tratado como un objeto numpy.

El método resize() de Python no es efectivo en este caso, ya que no tiene en cuenta el eje, y debido a esto no es capaz de extrapolar y/o interpolar.

El módulo opencv se usa en Python para  la visión por computadora  y el procesamiento de imágenes.

El procedimiento en esencia es leer primero la imagen empleando la función imread(), y luego cambiar su dimensión empleando función resize().

La sintaxis seria así:

dst = cv2.resize(src, dsize[, fx[, fy[, interpolation]]]])

Donde fx y fy son factores de escala a lo largo de los ejes x e y, dsize() se refiere al tamaño de la imagen de salida y el indicador de interpolación se refiere al método que vamos a usar.

Ya sea que se especifique (fx, fy) o dsize, OpenCV calcula el otro automáticamente.

Lo primero es disponer de opencv en el ordenador, para ello deberás descargarla y tenerla ya instalada. Puedes seguir las instrucciones acá .

import cv2
import numpy as np
img = cv2.imread('archivo.jpeg')
res = cv2.resize(img, dsize=(54,140),interpolation=cv2.INTER_CUBIC)

Podemos emplear como interpolación las siguientes:

Nearest Neighbor:

near_img = cv2.resize(img,None, fx = 10, fy = 10, interpolation = cv2.INTER_NEAREST)

la bilineal,

bilinear_img = cv2.resize(img,None, fx = 10, fy = 10, interpolation = cv2.INTER_LINEAR)

o la bicúbica que teníamos en el ejemplo inicial

bicubic_img = cv2.resize(img,None, fx = 10, fy = 10, interpolation = cv2.INTER_CUBIC)

Todas emplean algoritmos diferentes, y su efectividad varía de un caso a otro.

Y hasta aquí, esto es todo.

Espero que esto sirva de ayuda a alguien.

La ignorancia, es la muerte de los vivos

Como declarar un array en Python

logo python

En Python trabajamos constantemente con matrices de diferentes dimensiones. En este articulo vamos a ver como declarar un array en Python, usando dos formas.

Lo primero a considerar, es que en Python el primer elemento de una matriz, ocupa la posición 0, el segundo la posición 1 y así sucesivamente.

Declaración simple:

La forma mas sencilla de declarar que una variable recibe como datos un array es escribiendo el nombre de la variable el signo igual y corchetes:

mi_array = []

Esto indica al interprete de Python que mi_array es un array que de  momento esta vacío.

En este caso estamos accediendo al modulo list()

Se puede acceder a los elementos de la lista simplemente pasando el índice requerido. Dicho entonces, se entiende que mi lista[2] accederá al tercer elemento.

Para añadir un elemento usamos el módulo append() con el elemento que se agregará, teniendo en cuenta que append() lo colocará al final.

Si deseamos colocarlo en una posición especifica, se usa la función insert(x, y)  donde el índice es  x, e  y el valor y.

Si el índice tiene un valor negativo es porque estamos accediendo a las posiciones contando de atrás hacia adelante, o sea en orden inverso.  

mi_matriz = [1,2,3,"s",5]
print(mi_matriz [-2])
mi_matriz.insert(4,6)
print(mi_matriz [-2])
mi_matriz.append('f')
print(mi_matriz)
 output
s
12
[1, 3, 5, 7, 9, 's', 12, 'f', 'g']

La clase array

El modulo array permite inicializar un array que incluirá  solo elementos homogéneos.

Para usarlo debe importarlo como cualquier otro modulo, y viene de la librería array.

Este se define con paréntesis y acepta dos argumentos,  el type code que define el tipo de los elementos que lo integran; el segundo parámetro es la lista de estos elementos entre corchetes.

Para acceder a un elemento del array, se emplea la función index(x) donde x es el índice del array.

Para insertar un nuevo elemento en el array, se llama a la función insert(i,x), donde es el índice y x es el valor a insertar.