CREANDO CALCULADORA DE DIVISAS CON PYTHON Y TKINTER.

Destacado

Bienvenidos una semana más a vuestro blog sobre programación en Python, en una ocasión en las que nos disponemos a crear una aplicación con interfaz gráfica (usando ‘Tkinter‘) que calcule el cambio actual entre distintas divisas, utilizando los datos actualizados que nos proporciona ‘Yahoo Finance‘.

COMO FUNCIONA.

El manejo de nuestra aplicación es bien sencillo: El usuario elige las dos divisas de una lista desplegable y luego ingresa la cantidad que desea convertir. Al hacer clic en el botón «CALCULATE«, el programa solicita la tasa de cambio actualizada a través de la biblioteca ‘yfinance‘. Así, una vez obtenida la tasa de cambio, se realiza el cálculo y se muestra el monto convertido en la etiqueta central.

Para construir nuestra aplicación, y dado que necesitaremos descargarnos datos actualizados con ‘yfinance‘, deberemos proceder, antes de nada, a instalar esa librería en nuestro sistema:

Una vez que tengamos ‘yfinance‘ descargado, podremos empezar a escribir nuestra aplicación. Para lo que empezaremos importando las librerías y módulos que vayamos a utilizar:

En esta ocasión, usaremos ‘Tkinter‘ para confeccionar la interfaz, ‘yfinance‘ para obtener los datos de cambio entre divisas actualizados, ‘os‘ para mostrar el directorio de ejecución de la aplicación y ‘threading‘ para evitar bloqueos en el programa, cuando este hace la petición a ‘Yahoo Finance‘.

CREANDO LA INTERFAZ.

El primer paso en la elaboración de nuestra aplicación será el consistente en definir algunas variables iniciales, así como la creación de la ventana y elementos gráficos de nuestra aplicación. Para ello crearemos la clase de nuestra aplicación, en cuyo constructor empezaremos definiendo algunas características tales como el nombre de la ventana, sus dimensiones y la variable «currencies«, un diccionario en el que definiremos el nombre y ticker de las distintas divisas entre las que se va a poder efectuar los cálculos:

Tras ello, incluiremos un espacio en la parte superior de la ventana, en la que se mostrará la dirección del directorio en el que se está ejecutando nuestra aplicación. Dicho directorio lo obtendremos con el modulo ‘os‘ y el método ‘.get()‘:

Tras ello, crearemos las dos listas desplegables en las que se van a mostrar las divisas que definimos en la variable ‘currencies‘:

Pasemos ahora a crear tanto el ‘entry‘ para la cantidad a computar (así como a su variable asociada ‘self.amount‘) como la etiqueta en la que se mostrará el resultado final:

Finalmente (en lo que a la elaboración de la interfaz se refiere) incluiremos, en la parte inferior, el conjunto de botones que vamos a usar para interactuar con el programa, para finalizar haciendo la llamada a su ejecución:

Con ello tendríamos completada la parte puramente gráfica de nuestra aplicación. En efecto si ejecutamos lo hecho obtendremos el siguiente resultado:

OUTPUT:

No obstante, nuestra aplicación aún no hace nada (salvo mostrar en los desplegables, las divisas entre las que podemos elegir). Para hacer que podamos obtener la información deseada, tendremos que crear una serie de funciones que se ocupen de la lógica del programa.

PROGRAMANDO LÓGICA.

Puesto que el resultado que queremos obtener depende de la cantidad que ingresemos a través de los botones numéricos, lo lógico será empezar implementando una función que permita construir dicha cantidad y mostrarla en el ‘entry‘. A dicha función la llamaremos ‘btnClick()‘:

Como se ve, se trata de una función bien sencilla que toma el valor (‘num‘) establecido mediante una función lambda, en la variable ‘command‘ del botón correspondiente, y lo agrega a la variable «amount» ocupándose a la vez, de no admitir más que una coma en el entry.

Usando funciones ‘lambda’ para los botones numéricos.

Como es natural, junto a una función que escriba un número en pantalla, implementaremos otra que se encargue de borrarlo. A esta última la llamaremos ‘reset_display()‘ y ejecución vincularemos con el botón ‘RESET‘:

Función ‘reset_display’

Con esto ya tendríamos las funciones encargadas de introducir el input en nuestra aplicación. A partir de aquí usaremos dos funciones: Una que se encargue de crear el ticker cuyos datos de cierre vamos a pedir a la API de Yahoo Finance y otra que multiplique el valor introducido en el entry por el valor de cambio recibido la mencionada API. La primera de ellas, se llamará ‘create_ticker()‘ y devolverá la concatenación de los valores asociados a las claves seleccionadas en las listas desplegables más el string ‘=X‘:

La segunda de ellas es la que hemos llamado ‘calculate()‘ y, después de llamar a la anterior, usa ‘yfinance‘ para descargar el último dato disponible y multiplicarlo por el monto introducido para obtener el resultado final que se mostrará en la etiqueta central:

Una sentencia ‘try‘/’except‘ evitará que el programa falle, en caso de que se produzca algún problema imprevisto o una omisión por parte del usuario a la hora de introducir los datos. Mostrando la correspondiente ventana de error:

Finalmente, para evitar que al realizar la petición, la ventana pueda quedarse congelada o bloqueada, usaremos una tercera función que se encargue de ejecutar esta última de manera concurrente. A esta función la hemos llamado ‘init_task()‘ y es la que finalmente vincularemos con el botón ‘CALCULATE‘:

De este modo los valores ‘command‘ para todos los botones, quedaría como sigue:

OUTPUT:

Y con ello ya tendríamos creada nuestra aplicación para conversión de montos de dinero en diferentes divisas. A partir de este punto, podéis continuar desarrollando la aplicación, añadiendo opciones, funcionalidades o introduciendo más divisas a las listas desplegables.

En el siguiente enlace podéis acceder al código completo del script, para que podáis probarlo por vosotros mismos:

https://github.com/antonioam82/Calcu/blob/master/CURRENCY_CALC.py

Saludos.

‘RADIOBUTTONS’ CON PYTHON Y TKINTER.

Saludos programadores, en el artículo de hoy, vamos a ver un sencillo ejemplo de como hacer uso de la función «Radiobutton()» en tkinter con la que podremos introducir en nuestras interfaces una serie de opciones que podrán ser marcadas por el usuario de nuestro programa. Se trata este de un elemento, también, muy utilizado para la confección de formularios:

Veamos ahora como crear nuestro widget paso a paso. Lo primero que haremos será importar ‘tkinter‘ y generar nuestra ventana principal, estableciendo su tamaño:

OUTPUT:

Generada nuestra ventana, es hora de empezar a introducir los elementos a seleccionar, además de un botón de «RESET» y una etiqueta, en principio sin texto, en la que mostraremos la opción seleccionada. Para hacer uso de estos elementos emplearemos las funciones «Radiobutton()«, «Button» y «Label» definiendo para el caso de las opciones a seleccionar y del botón, las funciones a las que vamos a llamar. También cabe destacar el argumento «value» de «Radiobutton()» con el que indicaremos la variable a la que nos estamos refiriendo (en este caso «option«):

Una vez definidos los elementos de la interfaz, definiremos también las funciones «select()» y «reset()» a la que referenciamos con el argumento «command» y que se encargarán de mostrar en la etiqueta de salida («outLabel«) la opción seleccionada, en el primer caso y de resetear la opción escogida, en el segundo:

OUTPUT:

También podemos utilizar las variables «activebackground» y «activeforeground» para establecer el color de fondo y texto, que adoptarán los «radiobuttons» al hacer click sobre ellos:

OUTPUT:

Y hasta aquí este sencillo ejercicio en el que hemos visto, de forma sencilla, como podemos incluir este widget para selección de opciones, en nuestras interfaces de usuario utilizando tkinter.

En el siguiente enlace podéis ver el código completo de este ejercicio:

https://github.com/antonioam82/ejercicios-python/blob/master/radiobuttons.py

Saludos.

PROGRAMANDO BLOC DE NOTAS CON PYTHON Y TKINTER (EJERCICIO PRÁCTICO)

Quienes sigan este blog con cierta asiduidad, sabrán que en «El Programador Chapuzas» a menuda nos gusta realizar ejercicios prácticos en los que programamos alguna aplicación con nuestro lenguaje favorito. Pues bien, siguiendo con esa línea, hoy nos proponemos crear un sencillo bloc de notas ayudándonos de la librería para creación de interfaces gráficas, «Tkinter«.

Se trata de un sencillo ejemplo para el cual no necesitaremos instalar ningún recurso externo a las librerías nativas de Python. Con lo que simplemente bastará con importar las librerías y recursos que vayamos a utilizar:

PROGRAMANDO INTERFAZ GRÁFICA.

Como acostumbramos a hacer cuando creamos una aplicación de estas características, lo primero que haremos será crear nuestra interfaz gráfica de usuario. Proceso que iniciaremos definiendo la ventana en la que vamos a insertar los elementos de la misma:

OUTPUT:

Una ves que hemos creado la ventana de nuestra aplicación, definiendo sus dimensiones, color de fondo y título, es hora de empezar a añadir los diferentes elementos para interactuar con la aplicación. Empezando por una salida en la parte superior, que muestre el directorio en el que se está ejecutando nuestro programa. Para ello crearemos un elemento de entrada (con «Entry()«) en el que se mostrará el valor de una variable tipo «StringVar()» a la que hemos llamado «current_dir» que será igual al directorio de ejecución actual (que obtendremos con «os.getcwd()):

OUTPUT:

Debajo del elemento anterior, insertaremos 4 botones («Open«, «Save«, «Clear» y «Exit«) destinados a abrir un documento ya existente, guardar uno nuevo, borrar el contenido actual y salir, respectivamente. Para la creación de estos usaremos la función «Button()» (definiendo el texto de los mismos así como su posición) no sin antes crear un contenedor «Frame()» para albergar a dichos botones y que ubicaremos en la parte superior de la ventana con un guardando un margen horizontal de 10 y uno vertical de 5:

OUTPUT:

Finalmente crearemos el espacio para escribir texto junto a una barra de desplazamiento vertical que ubicaremos a su derecha. Esto lo haremos en 4 pasos: 1º- Creamos un espacio «Canvas()» en el que ubicaremos ambos elementos con margen horizontal de 10 y vertical de 5 indicando a su vez que queremos que rellene todo el espacio disponible. 2º- Crearemos la barra de scroll lateral, posicionándola en el lado derecho y usando la función «Scrollbar()«. 3º- Crearemos el espacio para escribir texto, mediante la función «Text()» definiendo un color de fondo, una fuente tipográfica así como su posición y 4º- Una vez creados el espacio para texto y la barra de desplazamiento lateral, usaremos «yscrollcommand» (para el espacio de entrada y «command» (para la barra de desplazamiento) para conectar ambos elementos, de modo que e el momento de llegar el texto al final, se active dicha barra.

OUTPUT:

Y con esto ya tendríamos elaborada la interfaz de nuestro bloc de notas. Ahora la siguiente fase será la de definir las funciones que harán que nuestro programa sea capaz de abrir archivos y guardar archivos nuevos, entre otras cosas.

PROGRAMANDO FUNCIONES.

Como ya hemos apuntado, ahora nos disponemos a definir las funciones que realizarán los botones que hemos creado, empezando por el primero de ellos «Open» que se encargará de abrir archivos de texto ya creados. Para este cometido, definiremos 2 funciones a las que llamaremos «openFile()» y «clearFile()«. Dichas funciones (al igual que las demás) las definiremos fuera del bloque que hemos utilizado para crear la interfaz:

Tenemos así una función «openFile()» que usará el método «askopenfile» para abrirnos un explorador de archivos, con el que podremos elegir el documento de texto que queramos abrir (cuta información se guardará en la variable «file») de modo que a continuación, el valor de este no es nulo (por no haber cerrado el explorador sin seleccionar) se procederá a la ejecución de la otra función «clearFile()» que borrará la información que pueda haber en el espacio de texto (usando el método «.delete()») en caso de que dicho espacio de texto no esté en blanco («if len(entry.get(‘1.0’,END))>1«). Finalmente se procederá a la lectura del archivo seleccionado almacenándose su información en la variable «content«, que a su vez se mostrará en el espacio de texto («entry.insert(INSERT, content)«). Finalmente para que esto pueda funcionar, tendremos que añadir el atributo «command» al botón correspondiente, indicando la función a ejecutar al presionar sobre el:

A su vez, ya que tenemos un botón «Clear» para borrar contenido del área de texto, agregaremos un «command» a este, que ejecute la función «clearFile()«:

Pasemos a programar la función a ejecutar al presionar el botón «Save«: Para ello definiremos una nueva función a la que llamaremos «saveFile()«:

Como sucedía en la función «openFile()«, en este caso, condicionaremos la ejecución del código a que haya algo escrito en el espacio para texto («if len(entry.get(‘1.0’,END))>1:«). En ese caso, utilizaremos «asksaveasfilename()» para abrir el explorador de archivos, pero en este caso para elegir el destino de nuestro nuevo archivo de texto (al que daremos el nombre por defecto de «my_text«, que el usuario podrá cambiar). Una vez elegido destino sin cerrar antes el explorador («if doc != «»«), utilizaremos las funciones «open()» para abrir en modo escritura el nuevo archivo («new_file = open(doc,»w»)«), «write()» para escribir en el la información que haya escrito en el área de texto («text = str(entry.get(‘1.0’, END))«) y «close()» para cerrar el archivo recién creado. Como antes, para que esto se ejecute, agregaremos el correspondiente «command» al botón «Save«:

Finalmente, definiremos una función «destroy_window()» que emplearemos para cerrar nuestro bloc de notas, con la peculiaridad de que, en caso que haya algo escrito en el espacio de texto, nos mostrará una ventana en la que se nos ofrecerá la posibilidad de guardar los cambios realizados (dicha ventana la generaremos usando el método «askquestion()» para luego usar la función «saveFile()» antes definida para guardar los cambios en un archivo) antes de cerrar la ventana con «.destroy()«:

Como en los casos anteriores añadiremos el «command» para el botón «Exit«, indicando la función a ejecutar:

OUTPUT:

Y con ello ya tendríamos hecho nuestro bloc de notas con Python y Tkinter. Un proyecto sencillo que nos ha ayudado a recordar y aplicar conceptos clave a la hora de programar aplicaciones gráficas en Python y cuyo código completo (al que se le ha añadido la posibilidad de copiar texto usando «threading» y «pyperclip«) podéis visitar en el siguiente enlace:

https://github.com/antonioam82/ejercicios-python/blob/master/notepad.py

Saludos.

CREACIÓN DE MARCOS («LABEL FRAMES») EN TKINTER.

Saludos y bienvenidos nuevamente a este sitio en el que tratamos los diferentes aspectos y funcionalidades relacionadas con la programación en lenguaje Python. En esta ocasión (tal y como reza el título) vamos a aprender a crear marcos (label frames) en Tkinter la cual (para quién no lo sepa) constituye una de las librerías más usadas en Python a la hora de crear interfaces gráficas que nos faciliten la interacción con nuestros programas.

Un marco consiste en un contenedor en el que, a su vez, podemos alojar otros widgets, y que nos sirve para organizar mejor el espacio en nuestra interfaz, agrupando dentro de un mismo marco, elementos o widgets que puedan estar más relacionados. La creación de estos en Tkinter es bien sencilla, simplemente hemos de utilizar la función «LabelFrame()» tal y como se muestra en este sencillo ejemplo:

OUTPUT:

Como se ve en el código, hemos empezado creando nuestra ventana («root«) en la que después hemos incluido nuestro contenedor empleando la función «LabelFrame()» y pasándole varios argumentos: El nombre de la ventana en la que vamos a insertarlo («root«), el texto que vamos a darle («Buscador«) y que aparecerá en la parte superior izquierda, el color de dicho texto (‘blue’) y los valores relativos a los márgenes que queramos que guarde con respecto a los elementos insertos en su interior («padx» y «pady«). Tras ello hemos procedido a insertar en dicho marco dos elementos: Uno de tipo entrada («Entry«) y un botón («Button«) los cuales hemos emplazado usando el método «.grid«. Nótese aquí que para que estos dos elementos se integren dentro de nuestro marco, debemos indicar el nombre que hemos dado al marco («buscador«) como primer argumento a introducir al usar las respectivas funciones «Entry» y «Button«.

Como hemos dicho, podemos usar los valores «padx» y «pady«, dentro de la función «LabelFrame()» para cambiar las dimensiones de la misma respecto de la los elementos que tenga dentro. Así, en nuestro ejemplo, si reducimos su valor a la mitad, veremos como nuestro marco se encoje:

OUTPUT:

Un efecto similar obtendremos, esta vez respecto de la ventana principal, cambiando los referidos valores dentro del método «.grid()«:

OUTPUT:

Y con esto ya tenemos las bases para empezar a trabajar con marcos en nuestras interfaces gráficas, lo que nos permitirá crear diseños más ordenados y de aspecto más profesional.

Saludos.

LIMPIEZA DE PANTALLA CON PYTHON USANDO «os» Y/O «subprocess».

En este blog, hemos hablado acerca de la creación de diversas aplicaciones en las que el usuario interactúa con el programa usando una interfaz gráfica (GUI). No obstante, en ocasiones, podemos querer que dicha interacción se realice mejor usando la línea de comandos. Uno de los inconvenientes que se da en estos casos es que, sobre todo para ciertos programas, se puede generar gran cantidad de información en pantalla que dificulta el manejo del mismo. Es por ello que realizar una limpieza de pantalla constituye una función interesante para solventar tal incomodidad. Esta operación (al igual que muchas otras de las que no vamos a hablar aquí) se puede realizar mediante el uso de dos módulos: «subprocess» y «os«.

EJEMPLO USANDO «subprocess»:

Uno de los módulos que podemos emplear es «subprocess«, el cual emplea los comandos del sistema operativo (en adelante «SO») de ejecución para realizar distintas acciones, entre las que se encuentra el limpiado del shell. Dicho comando dependerá del SO en el que estemos ejecutando nuestro código. Así, en un sistema «Windows» lo haremos de la siguiente manera aplicada a un sencillo ejemplo:

Tenemos aquí un sencillo script (al que hemos llamado «saludo.py«) en donde el bucle del programa simplemente nos pide un nombre, para luego imprimir un saludo personalizado, 20 veces en pantalla, tras lo cual nos preguntará si queremos continuar. De modo que si introducimos «s» se limpiará la pantalla para pedirnos nuevamente el nombre, y si introducimos otra cosa se realizará dicha limpieza para finalizar el programa:

Lo importante de este ejemplo es como hemos usado el método «.call» del módulo «subprocess» para llamar al comando de Windows (en nuestro caso) encargado de realizar la limpieza de pantalla cada vez. Este procedimiento tiene sin embargo un inconveniente importante. Y es que el procedimiento que usa para realizar la acción de limpieza depende directamente del SO que estamos usando, lo cual hace que si quisiéramos ejecutar el programa en otro tipo de SO (por ej: en un Linux o en un Apple) se produciría un error. En pocas palabras, que el uso de nuestro programa quedaría limitado a sistemas Windows. Para ello en su lugar, podemos usar el módulo «os«.

EJEMPLO USANDO «os»:

El módulo nos permite realizar la limpieza de pantalla usando el comando correspondiente para cada SO. Información que obtendremos mediante el método «.name«:

Pasemos a continuación a aplicar el procedimiento usando «os» a nuestro script «saludo.py» para entenderlo mejor:

En este caso tenemos nuestro script «saludo.py» el cual al ser ejecutado, hará exactamente lo mismo que en el ejemplo anterior. La diferencia aquí estriba en el hecho de que la limpieza de pantalla se efectuará exitosamente (usando el método «os.system()«) para diferentes SOs (no solo Windows como el caso anterior). Esto es así debido a que en este caso usaremos los valores «cls» y «clear» dependiendo de si el SO en el que se ejecuta es Windows u otro (como Linux o Mac) respectivamente.

CUANDO USAR CADA UNO…

Antes de finalizar, una duda que puede salirnos al paso es cuando usar uno u otro módulo. La respuesta viene dada por el uso que queramos darle a nuestro «script». Esto es así en la medida que en aquellos casos en los que queramos realizar una operación de interacción con el SO muy especifica (que consideremos que vamos a aplicar únicamente en nuestro propio ordenador) el uso «subprocess» puede ser la opción más cómoda y directa. No obstante, si nuestra intención es publicar nuestro programa para que sea usado por distintos usuarios (quienes podrán usar SOs diferentes al nuestro) y darle portabilidad a nuestro programa, el empleo del módulo «os» será sin duda la opción más segura.

Saludos.

APLICACIÓN GRÁFICA PARA GENERACIÓN DE CONTRASEÑAS CON PYTHON.

Bienvenidos una vez más a vuestro blog sobre programación en lenguaje Python. En esta ocasión (y tal y como indica el título sobre estas líneas) nos disponemos a crear una sencilla aplicación gráfica (cuyo código íntegro podéis ver en el enlace que dejo al final del artículo) para generar contraseñas, cuya longitud, número mínimo de mayúsculas, minúsculas, números y caracteres especiales podrán ser definidos por el usuario de la aplicación. A su vez incorporaremos una función de guardado y otra de copiado de la contraseña recién creada. De modo que nuestra interfaz tendrá, al final, un aspecto tal como este:

Para la mencionada función de copiado usaremos la librería «pyperclip«, la interfaz será hecha con «Tkinter«. A su vez, usaremos «random» para la generación aleatoria de las contraseñas, «os» para mostrar el directorio de ejecución en la parte superior y «threading» para ejecutar parte del código en segundo plano. Todos estos elementos y recursos deberemos importarlos al comienzo de nuestro código:

Hechas las importaciones pertinentes, procedemos a crear nuestra clase (a la que llamaremos «app«) que contendrá la interfaz del programa y las funciones que lo harán funcionar:

En este bloque tenemos dos partes bien diferenciadas: En la primera procedemos a crear la ventana de nuestra aplicación definiendo sus dimensiones y título. En la segunda pasamos a definir el valor inicial de algunas variables cuya utilidad veremos más adelante, y entre las que cabría destacar «self.numbs» (la lista de longitudes posibles para nuestra contraseña), «self.your_password» (que será el valor que se muestre en el espacio destinado a mostrar la contraseña generada), «self.currentDir» que mostrará el directorio actual de ejecución, (obtenido con «os.getcwd()«), «self.running» que indicará si la búsqueda de contraseña está o no activa, y la cadena de caracteres especiales que podrá contener la contraseña («self.special_chars«) la cual podrá contener la letra «ñ/Ñ» en el caso de que el idioma de nuestro sistema sea el español (el idioma del sistema lo podemos obtener con «getdefaultlocale()«).

Definidos estos primeros valores, pasaremos a introducir los diferentes widgets (compuesto por botones y cuadros de texto) de nuestra interfaz: Usaremos «Button()» para crear los botones, «Label()» para las etiquetas, «Entry()» para el espacio de texto y «ttk.Combobox()» para las listas desplegables. A su vez, estableceremos el 8 como longitud predeterminada para la longitud total de la contraseña y 0 para cada uno de las longitudes mínimas:

De este modo el usuario podrá definir tanto la longitud total de la contraseña así como la cantidad mínima de caracteres en mayúscula, minúscula, números y caracteres especiales. Con tal información nuestro programa podrá generar de forma aleatoria, nuestra contraseña probando diferentes combinaciones hasta dar con una que satisfaga los mínimos establecidos por el usuario. Para esta labor crearemos una función (de nombre «self.genera_password()«) que empezará tomando los valores de longitud y mínimos convirtiéndolos a formato entero («int()«):

Dado que vamos a generar cadenas de caracteres, crearemos una variable «characts» la cual contendrá todos los caracteres (mayúsculas, «minúsculas, numéricos y especiales) que se combinarán para generar nuestra contraseña (dichos caracteres se encuentran contenidos en «string.ascii_letters«, «string.ascii_digits» y «self.special_chars» (esta última definida por nosotros en el paso anterior). No obstante, imaginemos el caso en que el usuario quisiera una contraseña de 8 caracteres con un mínimo de 3 minúsculas, 4 mayúsculas y 1 caracter numérico, en este caso no sería necesario incorporar caracteres especiales a la cadena «characts«. Por ello introducimos dentro de la función el siguiente bloque:

En dicho bloque comenzamos definiendo la variable «characts» que albergará los distintos caracteres que nuestra aplicación va a combinar para generar la contraseña aleatoriamente (también definiremos una variable de posición con valor inicial 0). Tras ello, crearemos dos listas: «liats» que contendrá los objetos correspondientes a los distintos tipos de caracteres posibles y «sumas» que contendrá los valores mínimos para cada tipo de caracter. Finalmente prevemos la posibilidad de que la suma de los mínimos requeridos sea igual a la longitud total, habiendo al menos un mínimo de 0 de modo que los tipos con este valor no se incorpore a la lista de caracteres posibles «characts«. El sentido de esta operación estriba en la necesidad de que nuestro programa, al generar la contraseña no tome valores innecesarios para los que no va a ver lugar.

Una vez que tenemos nuestros posibles caracteres a combinar, pasaremos a a fase (recordemos que seguimos dentro de la función «genera_password()«) en la que generaremos la contraseña mediante la combinación sucesiva de tales caracteres hasta dar con una combinación que satisfaga los mínimos especificados por el usuario:

Según la longitud de contraseña que hayamos elegido, en combinación con según que numero de caraceres mínimos para cada tipo que hayamos establecido, el proceso de búsqueda puede tardar más o menos. Por ello, si este se demora en demasía, podemos detenerlo antes de tiempo, usando el mismo botón que para iniciarlo, sola que en este caso se ejecutará la función «cancel_process()«:

Incluimos también un bloque que mostrará debajo de espacio de texto, un mensaje relativo al final de la operación (para el caso que este haya finalizado sin cancelar) cuando esta se ha llevado a cabo o se ha interrumpido:

A su vez, para evitar que la ventana de nuestra aplicación se congele durante el proceso de búsqueda y obtención de contraseña. Haremos que dicho proceso (el relativo a la recién comentada función «genera_password()«) haremos que el botón «CREATE PASWORD» inicie la función «init_taks()» que ejecutará dicha función en paralelo a la principal. Dicha función se encargará a su vez de ejecutar la función solo si la suma de los mínimos requeridos no supera la longitud total requerida para la contraseña:

Finalmente nuestra aplicación incorpora dos funciones más: La función «save_password()» que almacenará nuestra nueva contraseña en un archivo de texto. Dado que el almacenar contraseñas en textos sin formato no está considerada una práctica recomendable por motivos de seguridad, antes de su efectiva ejecución mostraremos una ventana advirtiendo al potencial usuario de acerca de lo no recomendable de dicha práctica:

La segunda de dichas funciones, es la llamada «copy()» mediante la cual podremos copiar la contraseña generada para pegarla en el sitio en que vayamos a usarla (una ventana emergente nos indicará que nuestra contraseña está lista para ser pegada). Para ello utilizaremos la librería «pyperclip» de la que hablamos con anterioridad. Esta función se ejecutará siempre y cuando el proceso de búsqueda de contraseña esté detenido («self.running=False«) y se muestre algún resultado en la salida de texto («self.your_password.get()!=»»«):

Y con esto habríamos visto, a grandes rasgos, como crear una sencilla aplicación gráfica con la que poder generar contraseñas que luego podamos emplear para loguearnos en nuestras cuentas favoritas.

Finalmente, podéis ver el código completo de la aplicación en el siguiente enlace:

https://github.com/antonioam82/PasswordGenerator/blob/main/password_generator3.py

Saludos.

CAMBIANDO COLOR DE TEXTO EN PYTHON, CON «colorama».

Cuando estamos trabajando sobre la consola, a menudo necesitamos que en esta se muestre algún texto, sabemos también que este se va a mostrar siempre del mismo color. No obstante, el mostrar texto en diferentes colores, puede contribuir a que se diferencien mejor determinadas líneas del resto (por ejemplo para diferenciar las salidas de un programa de las entradas de usuario). Esto nos será especialmente útil cuando estemos creando aplicaciones que deban ejecutarse directamente en la consola (sin ningún tipo de interfaz gráfica).

Para dicho cometido, contamos en Python con «colorama» una librería que nos permitirá mostrar texto en distintos colores en la consola. Así, para trabajar con ella, tendremos que empezar por su instalación con el comando «pip» que ya conocemos:

Una vez instalado podremos empezar a realizar nuestras pruebas. Para ello importaremos la librería con los módulos que vamos a necesitar. Si estamos ejecutando el script en un entorno «Windows» escribiremos «init()» para iniciar «colorama«:

Como se ve, al hacer la importación, hemos incluido los módulos «Fore«, «Back» y «Style«, a través de los cuales vamos a poder modificar el color del texto, del fondo y la intensidad de este, respectivamente. Así, pongamos que queremos mostrar un sencillo texto en rojo:

Como se ve, para ello simplemente hemos sumado a nuestro texto el método RED (el color en cuestión) del módulo «Fore«:

De ese mismo modo podemos presentar nuestro texto en diferentes colores:

Aquí hay que señalar que una vez que establezcamos un color (a no ser que definamos otro) todo el texto que se mostrará después será de dicho color aunque no apliquemos el método visto:

Por ello, para restablecer el color de texto predeterminado usaremos «Fore.RESET» (para el caso del fondo usaríamos «Back.RESET«):

Pero tal y como señalamos al principio, también podemos usar los módulos «Back» y «Style» para definir el color del fono e intensidad del color, respectivamente. Em el caso de la intensidad, esta podrá ser baja («Style.DIM«), media («Style.NORMAL«) y alta («Style.BRIGHT«). Estas características pueden combinarse para un texto dado mediante el procedimiento de sumado ya visto:

Tal y como ya hemos señalado, para restablecer el fondo y color predeterminados, usaremos «Back.RESET» y «Fore.RESET«, respectivamente:

Hemos visto así, como podemos eliminar el color del texto, el color del fondo y el estilo, por separado. No obstante también podemos optar por eliminar todos los efectos de una vez, mediante «Style.RESET_ALL«:

Visto como funciona, podemos elaborar un sencillo script («ejemplo_colorama.py«) que nos muestre un texto y fondo) en cada uno de los colores disponibles. El código en cuestión podría ser el siguiente:

Como se ve, empezamos (al estar usando un entorno «Windows«) escribiendo «init()» para iniciar «colorama«. Tras ello, creamos las listas «FORES«, «BACKS» y «BRIGHTNESS» que contendrán los métodos que muestran los distintos colores de texto, fondo e intensidad del mismo, respectivamente. Tras ello crearemos la función «print_with_color()» que en un «for» aplicaremos para mostrar nuestro texto, en cada intensidad (lista «BRIGHTNESS«) disponible para cada color de texto («FORES«), mostrando el siguiente resultado al ejecutar:

Nótese aquí los tres primeros textos son de color negro, por lo cual no se ven al mostrarse sobre un fondo del mismo color.

Lo hecho para el color del texto, podemos hacerlo igualmente para el del fondo, partiendo del mismo código visto arriba:

En este caso, hemos usado un triple ciclo «for«, para representar cada intensidad disponible para cada color de fondo y para cada color de texto. La salida del código sobre estas líneas sería la siguiente:

Obteniendo las diferentes combinaciones de color de texto, fondo e intensidad que podemos aplicar a nuestro textos e interfaces.

Saludos.

SUAVIZADO DE IMAGEN EN ARCHIVOS DE VIDEO (APLICACIÓN).

Hola y bienvenidos a vuestro blog semanal sobre programación en Python. A lo largo de las cerca de 200 entradas publicadas durante los últimos 3 años, hemos visto diversas características y técnicas de manipulación de archivos de imagen (cambios geométricos, detección de contornos, aplicación de filtros…). Por su parte, respecto a los archivos de vídeo, sabemos que estos no son otra cosa que secuencias de imágenes, las cuales, también hemos aprendido como extraerlas de un archivo de vídeo (y también como generar un vídeo a partir de estas). Pues bien, hoy nos proponemos a aplicar esos conocimientos adquiridos (junto al los referentes al manejo de librerías y módulos tales como «Tkinter«, «os«, «Pil«,»ffmpeg«…) para desarrollar una aplicación destinada a suavizar la imagen de un archivo de vídeo, empleando el método de «Filtrado bilateral» disponible en la librería «opencv» con la que hemos trabajado en numerosas ocasiones. Finalizado el proceso, obtendríamos una aplicación cuya interfaz gráfica sería la siguiente:

Como se ve, se trata de una interfaz que cuenta con todos los elementos necesarios para nuestro fin: Una ventana en la que se mostrará el nombre del video original, un botón «SEARCH» para seleccionarlo, un botón «CANCEL» para cancelar el proceso de filtrado y otro botón «START FILTERING» para iniciar dicho proceso. A esto añadimos una barra de progreso con la que podremos seguir el procesado de los frames (o fotogramas) además de la generación del nuevo vídeo y dos etiquetas en las que se mostrará el «frame rate» (atributo necesario para darle la misma velocidad y duración al nuevo vídeo con respecto al original) y el número total de frames del vídeo seleccionado (que nos servirá para mostrar correctamente el proceso en la barra de progreso).

FUNCIONAMIENTO: Lo que nuestro programa (cuyo código completo podéis ver en el enlace que dejamos al final) va a hacer es tomar el vídeo cuya calidad de imagen queremos mejorar, y descomponerlo en los ‘frames’ que los componen, a medida que cada uno de estos, va siendo tratado por la función de filtrado. Una vez que tenemos la lista con todos los ‘frames’ modificados, se generará un nuevo vídeo, con dicha información, aplicando el ‘frame rate‘ del vídeo original, una vez creado el nuevo vídeo, el programa pasará a añadirle el audio (en caso que lo tenga) del original, el cual, se habrá almacenado temporalmente en nuestra carpeta de destino.

Visto a grandes rasgos el modo en que va a funcionar nuestro programa, iniciaremos su programación en Python, importando los recursos que vamos a emplear, asegurándonos de tener todas las librerías y recursos necesarios, instalados:

Importamos aquí una serie de recursos entre los que podemos destacar «Tkinter» (para nuestra interfaz), «opencv» (para el tratamiento de los frames), «ffmpeg» (para la obtención del número de frames y el «frame rate» del video original) y «pydub» y «mhmovie» (para la extracción del audio del original y posterior incorporación al nuevo video).

Hecho esto, comenzaremos creando nuestra clase «app» en la que tras establecer el título («tittle()«), las dimensiones («geometry()«) de la misma y el color del fondo («configure(bg)«) procederemos a definir algunas variables iniciales como es el directorio de ejecución («self.current_dir()«), el nombre del vídeo original («self.filename()«), la lista en la que se almacenará la información correspondiente a los frames ya filtrados («self.frame_list«) y el nombre del futuro video resultante («self.vid_name()«):

Tras ello, procederemos a definir los diferentes elementos gráficos de nuestra interfaz utilizando los métodos que ya conocemos: «Button()» (para los botones) «Label()» (para las etiquetas) «Entry()» para espacios de entrada/salida de texto y «Progressbar()» para nuestra barra de progreso:

Pasemos a continuación a ver las distintas funciones de nuestro programa. Tal y como dijimos antes, el nuevo vídeo generado, lo será a partir de uno original que deberemos seleccionar. Luego la primera función que veremos es la encargada de seleccionar dicho archivo y a la que hemos llamado «self.open_file()«:

Lo que hace esta, al ejecutarse es abrir una ventana de nuestro sistema de archivos para seleccionar el vídeo que queremos filtrar, almacenándose la ruta al mismo en la variable «self.dir()«. Una vez cargado el archivo de video, usaremos la librería «ffmpeg» para obtener algunos datos del vídeo original, tales como el número total de frames («self.nframes«), y los frames por segundo («self.profile«). También obtendremos el nombre del vídeo, aislando este del resto de la ruta (variable «self.vidName«). Estos datos los mostraremos en la interfaz mediante los métodos «set()» y «configure()«.

Una vez seleccionado el archivo de vídeo, iniciaremos el proceso de filtrado mediante la función «self.filtering()«, la cual, tras obtener el directorio en el que queremos que se genere el nuevo archivo de vídeo, llevará a cabo la extracción del audio del vídeo original (que se almacenará temporalmente en el directorio de destino) siempre que nuestro video incorpore un audio, de modo que en caso contrario no se llevará a cabo dicha acción, pasando a la siguiente orden:

Tras ese paso previo, iniciaremos la extracción de los «frames» (fotogramas) que componen el vídeo original, llevando a cabo la eliminación del ruido sobre cada uno, empleando la técnica de «Filtrado Bilateral» que en «opencv» efectuaremos mediante el método «bilateralFilter()«. A su vez a medida que vamos procesando los frames iremos usando las variables «dif» y «self.counter» (previamente definidas) para ir calculando el porcentaje de frames (sobre el total definido en «self.nframes«) procesados e ir así actualizando la barra de progreso:

A su vez, podremos usar el botón «CANCEL» en cualquier momento mara cancelar el proceso, ejecutando la función «self.cancel()» que volverá a habilitar los botones y restaurar la barra de progreso a su posición original con «.stop()«:

Una vez que hayamos incorporado a la lista «self.frame_list()» el conjunto de arrays con los valores de color modificados por la función «bilateralFilter()«, pasaremos a recorrer los elementos de la misma, esta vez, para generar un nuevo vídeo. Para este segundo paso, emplearemos la función «self.create_new_video()«:

En este caso, lo que hacemos es tomar los arrays contenidos en «self.frame_list» y añadirlos a la lista creada «frame_array«. El progreso de esta segunda fase, lo mostraremos nuevamente mediante la barra de progreso, para lo cual, definiremos previamente las variables oportunas.

Una vez reunida toda la información de los arrays de los fotogramas, a nuestro programa solo le restará finalizar el nuevo vídeo y añadirle el audio extraído del video original. Esto último se producirá siempre que el video creado (cuyo nombre queda establecido por la variable «self.vid_name«) no se encuentre ya ubicado en la carpeta de destino (en este caso antes de continuar, se nos preguntará si deseamos sobrescribirlo):

Conviene aclarar aquí, que en un primer momento se generan los archivos de audio y vídeo por separado (con los nombres «VidAudioInfo.mp3» y «filteredVideo.mp4» respectivamente). No obstante, estos serán combinados (haciendo uso de la librería «mh_movie«) de modo que, una vez creado el video final (ya con el nombre establecido en la variable «self.vid_name()«) eliminándose (con la función «os.remove()«) los archivos sobrantes, salvo en un supuesto que veremos a continuación, volviendo a la función «self.filtering()«:

En la parte final de «self.filtering()» una vez completada la labor de «self.create_new_video()» se mostrará la correspondiente ventana de «tarea completada» para luego eliminar (con «os.remove()«) los posibles archivos sobrantes, empezando por el audio del video original. Este se eliminará solo si se encuentra creado (ya que puede suceder que no se haya generado al no tener el video original, sonido). La misma comprobación hará con respecto al archivo de video temporal el cual, de haberse generado el final, el temporal, no siendo así en el caso contrario, en cuyo caso será renombrado.

Y así tenemos creada nuestra aplicación para suavizar la imagen en un archivo de vídeo aplicando como ya dijimos la técnica del «Filtrado Bilateral». Existen otras muchas técnicas de filtrado, pero hemos escogido esta por ser de las que dan mejores resultados (a pesar de ser también de las más lentas). No obstante podéis probar otros métodos de filtrado (o también cambiando los valores del kernel).

El código completo de la aplicación expuesta puede verse en el siguiente enlace:

https://github.com/antonioam82/Video-Filter/blob/main/Video_Filter.py

Saludos.

OBTENIENDO POSICIÓN DE LA «ISS», EN TIEMPO REAL, CON PYTHON E «ISS-INFO».

Saludos programadores y bienvenidos a vuestro blog sobre programación en Python, en una ocasión en la que vamos a hablar de una curiosa librería llamada «ISS-Info» que como se puede deducir de su nombre, nos proporciona en tiempo real, distintos datos acerca de la «Estación Espacial Internacional» («ISS» por sus siglas en inglés), los cuales usaremos después, para crear una sencilla aplicación con la que podremos ver sobre un mapa, la posición actual de la misma en su orbita alrededor de la Tierra:

Pero antes, empezaremos viendo de modo resumido el tipo de información que podemos obtener con esta librería, la cual deberemos instalar previamente en nuestro equipo mediante el comando «pip install ISS-Info«:

Una vez instalado podemos empezar a obtener información de la «ISS» como puede ser la posición (medida en longitud y latitud) actual de esta:

Otra función importante es «iss_people_in_space()» que nos devolverá el número y nombres de los tripulantes que hay a bordo de la estación actualmente:

A su vez, también podemos obtener información acerca de las próximas veces que la Estación pase sobre un punto concreto. Esto lo haremos con el método «iss_passes()» al que pasaremos la latitud y longitud del punto de interés, la altitud de dicho punto, y el número de veces del que queremos obtener información (los dos últimos parámetros son opcionales cuyos valores por defecto serán de 100m y 5 veces respectivamente):

Como se ve, para cada uno de lo próximos pasos (los 3 próximo en este caso), se mostrará el tiempo en segundos que estará sobre el punto de interés y el segundo en el que se iniciará el paso por dicho punto.

Por otra parte, puede suceder que queramos obtener la información respecto a una población cuyas coordenadas desconozcamos de antemano. Aquí puede ser de gran utilidad la librería «geopy» de la que hablamos en su momento. Así pongamos el caso que queremos conocer la información acerca del paso de la Estación sobre la ciudad de París:

Por otra parte, para cada paso sobre un punto, se nos devuelve el inicio de dicho paso en formato «timestamp» (el segundo exacto). No obstante podemos hacer esa información más legible pasando dicha información al formato de fecha usando el módulo «datetime«:

Esto nos indica que la próxima vez que la «Estación Espacial Internacional» pase por encima de la capital francesa será (al momento de escribir estas líneas) a las 11 horas, 32 minutos y 18 segundos del día 3 de Mayo de 2021.

CREANDO APLICACIÓN «ISS Tracker»:

Una vez vista la información que podemos obtener con «ISS_Info«, vamos a pasar a elaborar un sencillo script con el que monitorizaremos sobre un mapa (archivo «word.png«) la ubicación actual de la estación (que representaremos mediante el archivo «iss.gif«) en tiempo real, auxiliándonos a su vez de la librería «turtle» (de la que ya hemos hablado en alguna ocasión). Los dos archivos mencionados aparecen junto al código completo del programa, en el repositorio cuyo enlace dejo al final.

«word.png»
«iss.gif»

Para ello, empezaremos importando los recursos necesarios: «ISS-Info» para obtener la posición actual de la estación, «turtle» para establecer los elementos visuales del programa, «time» para definir cada cuantos segundos queremos que se actualicen los datos y «threading» para ejecutar el rastreo en paralelo:

Importados dichos recursos, pasaremos a crear el mapa sobre el que se va a desplazar nuestra estación:

Empezamos creando el objeto correspondiente a nuestra pantalla (al que llamaremos «screen«) usando el método «turle.Screen()» del que a continuación iremos definiendo atributos tales como el titulo («title()«) y dimensiones («.setup()«). A continuación, nos aseguraremos que el sistema de coordenadas de nuestro plano coincida con el sistema de coordenadas geográficas, de modo que en cada momento, nuestra aplicación refleje correctamente, la posición de la Estación en el plano. Para esto usamos el método «setworldcoordinates()» al que pasaremos los pares correspondientes a la longitud y latitud mínimas y máximas. Finalmente estableceremos el fondo de nuestra ventana («bgpic«) que consistirá en el archivo «world.png» antes aludido.

Una vez que tenemos creada nuestra ventana con el mapa «word.png» como fondo y establecido el sistema de coordenadas de posición, pasaremos a incluir el icono de la Estación (archivo «iss.gif«) el cual se ubicará en el centro del mapa al iniciarse el programa:

Pero no es en el centro del mapa donde nos interesa que esté nuestro icono. Por ello a continuación, pasaremos a definir la función («tracker()«) que lo irá desplazando por el plano, en función de los datos obtenidos cada 5 segundos mediante los métodos antes referidos para determinar la longitud y latitud actuales:

Como se ve, nuestra función consistirá básicamente en un bucle en el que cada 5 segundos se accederá a la información relativa a la posición actual de la Estación (variables «lon» y «lat«), plasmándose ambos valores en la parte superior de la ventana (modificando el valor para «screen.title()«) y moviendo el icono (que definimos con el objeto «iss«) hacia el punto del plano correspondiente usando el método «goto()«:

De esta manera siempre podremos saber de un modo rápido y directo, la ubicación de la Estación Espacial Internacional, en su viaje alrededor de la Tierra.

Tenéis el código completo del programa, junto a los archivos necesarios en la siguiente dirección:

https://github.com/antonioam82/ISS-Tracker

Saludos.

REPRODUCTOR DE AUDIO CON «tkinter» Y «pyaudio».

Bienvenidos una semana más a «El Programador Chapuzas» vuestra página sobre programación en Python en la que en esta ocasión nos proponemos programar un sencillo reproductor de audio (cuyo código completo podéis ver en el enlace que dejamos al final) con «tkinter«, el cual, tendrá la particularidad de permitirnos añadir nuestros temas (los cuales habremos buscado previamente a través de la navegación por nuestro sistema de carpetas) favoritos a un «listbox» de modo que podamos oírlo de modo directo seleccionándolo de la lista. Dicho esto, el reproductor que vamos a crear tendría este aspecto:

Como se ve, se trata de un reproductor que cuenta con algunos de los elementos típicos de este tipo de aplicaciones (contador de tiempo, espacio para mostrar el título, botón de búsqueda, de ‘play’, ‘stop’. A lo que e añade un botón para incorporar el archivo seleccionado a un ‘listbox‘ el cual mostrará su contenido cada vez que iniciamos la aplicación y que nos permitirá un acceso más directo a los archivos contenidos en el mismo.

Como solemos hacer, empezaremos creando el apartado gráfico de nuestra aplicación, no sin antes importar las librerías y recursos que vamos a emplear:

En este caso, importamos «tkinter» para la interfaz, «wave» para abrir los archivos de audio, «pyaudio» para reproducirlos, «threading» para los procesos en paralelo, «json» (del que hablamos la semana pasada) para serializar la información de acceso a los elementos del «listbox» y «os» para mostrar el directorio de ejecución.

Antes de continuar, nos aseguraremos de tener instalados todos estos recursos, de modo que aquel que no tengamos, procederemos a instalarlo mediante el comando «pip«:

Pasemos ahora a diseñas el aspecto gráfico de nuestra aplicación, empezando, como no, por definir las dimensiones de la ventana (mediante el método «geometry«) en la que se ubicarán los distintos elementos, el color de fondo (mediante el atributo «bg» del método «configure()«) y el título de la ventana (con el método «title()«):

El siguiente paso será el de ir introduciendo los diferentes elementos interactivos de nuestra interfaz, empezando por el temporizador, el espacio para el nombre del audio y los botones principales:

Como se ve, utilizamos las funciones «Button()«, «Label()» y «Entry()» para crear los botones, la etiqueta para el contador de tiempo y la entradas para mostrar el nombre del archivo abierto y el directorio de ejecución, respectivamente. Para la muestra del directorio de ejecución usamos la variable «self.currentDir» cuyo valor será el referido directorio que obtenemos con «os.getcwd()«. En este punto también crearemos la variable «self.filename» cuyo valor será el nombre del archivo abierto.

Pasemos a los elementos de la parte inferior, consistentes en dos botones para eliminar el contenido íntegro (o algún elemento) del «listbox» un «Label» indicador del número de elementos y el propio «listbox» al que asociaremos la pertinente barra lateral de «scroll». Aquí, a las funciones vistas antes, añadiremos la función «Listbox()» que mostrará los elementos guardados en nuestra lista de favoritos «self.fav_list«. Este elemento (al igual que las barras de scroll que crearemos mediante la función «Scrollbar()«) lo insertaremos dentro de un componente «Canvas» que habremos definido con anterioridad («self.canvas=Canvas(self.root)«):

Pasemos a continuación a crear las funciones que se encargarán de hacer funcionar nuestro reproductor. Aunque antes debemos tener en cuenta que para almacenar el título y ruta de los audios añadidos a la lista de favoritos (el «listbox«) almacenaremos tal información en un archivo «JSON» con estructura de diccionario y al que llamaremos «data.json» y que deberá estar ubicado en el mismo directorio de ejecución. No obstante podemos hacer que el programa, antes de mostrar la ventana compruebe si dicho archivo se encuentra presente en el directorio, creándolo en el caso de que no sea así:

Una vez asegurada la presencia del archivo «data.json«, haremos que se muestren los archivos guardados en el «listbox«. Esta función (a la que hemos llamado «show_list()» será la primera que se ejecute al iniciar el programa:

Ahora pasemos a definir la función de selección de archivo (que se ejecutará al clickar en el botón «SEARCH») a la que hemos llamado «open_file()«:

La función «open_file()» tiene como cometido, navegar por el sistema de archivos y carpetas para seleccionar el archivo (en formato «wav») que luego podremos reproducir y/o almacenar en nuestra lista de favoritos. No sin antes ejecutar las funciones «stop_music()» (para parar el audio que pueda estar reproduciéndose) y «if_any_selected()» que devolverá «True» o «False» en función de si hay o no, algún elemento seleccionado en las lisbox de modo que en caso afirmativo, proceder a deseleccionarlo con la función «selection_clear()«.

La función «is_any_selected()» recorrerá los elementos del listbox comprobando si se encuentra o no seleccionado. En cuyo caso se rompe el ciclo y devuelve el valor «True».

Una vez seleccionado el archivo, lo normal es querer reproducir el audio, para ello usamos las funciones «init_task()» (para iniciar con «threading» el proceso de reproducción en paralelo) y «music()» (para reproducir el archivo):

Tenemos aquí, en primer lugar la función «init_task()» que se encarga de iniciar el proceso en paralelo consistente en ejecutar la función «music()» (encargada de reproducir el audio haciendo uso de las librerías «wave» y «pyaudio«). Dicha función «init_task()» se inicia ejecutando «is_any_selected()» para comprobar si hay algún elemento seleccionado en el listbox. Esto es importante en la medida que de estar seleccionado algún elemento, el archivo a leer será ese.

A su vez, también crearemos la función (a la que hemos llamado «add()«) encargada de añadir un archivo abierto al lisbox de modo que el acceso a este sea más rápido la próxima vez que ejecutemos el programa:

Del mismo modo que hemos creado una función para añadir elementos a la lista de favoritos, también crearemos otras dos funciones encargadas de eliminar la totalidad de los elementos o solo uno previamente seleccionado. Para ello usaremos las funciones «remove_playlist()» y «remove_from_list()«:

Nótese que en ambos casos, antes de ejecutarse la acción que modifica el contenido de «data.json«, usamos la función «messagebox.askquestion()» para que el usuario confirme la realización de la misma:

Finalmente, definiremos las funciones encargadas de hacer funcionar el contador de tiempo durante la reproducción de los audios. Dichas funciones son «clear_counter()» (para establecer el valor inicial de los minutos, segundos y horas), «counter_format()» (para mantener durante toda la ejecución el formato de dos dígitos para los minutos y segundos) y «timer_count()» (para representar el transcurso del tiempo en el marcador durante la reproducción):

Estas serían las funciones que nos permitirán hacer funcionar nuestro reproductor. Eso sin olvidar que algunas de ellas se han de ejecutar al pinchar en un determinado botón. Por ello para terminar, usaremos el atributo «command» para vincular cada botón con la ejecución de la correspondiente función:

Dejando a nuestra aplicación lista para ser usada.

Tal y como señalamos al principio de este artículo, en el siguiente enlace encontrareis el código completo del programa junto con el archivo «data.json«:

https://github.com/antonioam82/Music-Player

Saludos.