{ "cells": [ { "cell_type": "markdown", "id": "23083d5e-3082-4a08-a19b-1a86778a6575", "metadata": {}, "source": [ "# C: Ficheros, ejecución de scripts fuera de ```JupyterLab``` y ejecución de programas externos\n" ] }, { "cell_type": "markdown", "id": "d1f7e64c-85c3-4b44-8f4f-cc1a901c958c", "metadata": {}, "source": [ "## Trabajar con ficheros\n", "\n", "En ```Python``` podemos encontrar varias funciones que nos permiten trabajar con ficheros: podemos abrirlos, crearlos, leerlos, escribirlos, borrarlos, moverlos, obtener meta-información sobre ellos, etc. Veámoslo con ejemplos:" ] }, { "cell_type": "code", "execution_count": 1, "id": "c0bac961-6308-4dae-9ded-9e834e42f5c1", "metadata": {}, "outputs": [], "source": [ "f = open(\"salidas/miFichero.txt\", \"w\")\n", "\n", "f.write(\"Grabamos una cadena de texto en un fichero.\\n\")\n", "f.write(\"Y otra cadena más\")\n", "\n", "f.close()" ] }, { "cell_type": "markdown", "id": "da41d93c-07aa-4151-864a-6b1975f3db5c", "metadata": {}, "source": [ "+ La función ```open()``` abre un fichero llamado ```miFichero.txt``` con el modo de \"escribir\" (```\"w\"```) en él. Devuelve un objeto de tipo ```file```. Los modos básicos de apertura de ficheros son:\n", " + \"w\": Modo escritura (crea el fichero si no existe. Si existe borra el contenido)\n", " + \"r\": Modo lectura\n", " + \"a\": Modo añadir (crea el fichero si no existe. Si existe se añadirá el contenido al final).\n", " + En realidad hay [más modos de apertura y modificadores](https://docs.python.org/3.5/library/functions.html?highlight=open#open).\n", " \n", "+ ```.write()``` es un método que escribirá la cadena que pasemos como parámetro en el fichero.\n", "+ ```.close()``` es el método que cierra el fichero y se asegura que los datos se terminan de escribir en el archivo (```flush```). Es **MUY** importante cuando trabajemos con archivos cerrarlos para asegurarnos su integridad." ] }, { "cell_type": "code", "execution_count": 2, "id": "4ee32bf2-991c-4418-aa27-5d4a466aceee", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Grabamos una cadena de texto en un fichero.\n", "Y otra cadena más\n" ] } ], "source": [ "f = open(\"salidas/miFichero.txt\", \"r\")\n", "\n", "contenidoFichero = f.read()\n", "\n", "f.close()\n", "\n", "print(contenidoFichero)" ] }, { "cell_type": "markdown", "id": "80bced08-ebac-46ca-a969-a1e924a3c1a4", "metadata": {}, "source": [ "+ ```.read()``` es el método que permite leer el contenido de un fichero y lo devuelve como una cadena." ] }, { "cell_type": "code", "execution_count": 3, "id": "1c22880e-bf39-4e9d-a5f9-befb70621e63", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['Grabamos una cadena de texto en un fichero.\\n', 'Y otra cadena más']\n" ] } ], "source": [ "f = open(\"salidas/miFichero.txt\", \"r\")\n", "\n", "lineas = f.readlines()\n", "\n", "f.close()\n", "\n", "print(lineas)" ] }, { "cell_type": "markdown", "id": "67a307d1-9cd3-469c-a0d2-618aedb0f4d2", "metadata": {}, "source": [ "+ ```.readlines()``` es el método que lee el fichero pero lo devuelve como una lista de cadenas de caracteres (una por línea)." ] }, { "cell_type": "code", "execution_count": 4, "id": "d2ecba96-7147-4bfd-8d33-717766d00fc7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Grabamos una cadena de texto en un fichero.\n", "\n", "Y otra cadena más\n" ] } ], "source": [ "f = open(\"salidas/miFichero.txt\", \"r\")\n", "\n", "linea = f.readline()\n", "\n", "while linea != \"\":\n", " print(linea)\n", " \n", " linea = f.readline()\n", " \n", "f.close()" ] }, { "cell_type": "markdown", "id": "d6110136-c737-4ba8-9a44-dff19234ff00", "metadata": {}, "source": [ "+ ```.readLine()``` es el método que nos permite ir leyendo el fichero línea a línea, lo que puede ser útil para ficheros muy grandes que no queramos cargar de una sola vez." ] }, { "cell_type": "markdown", "id": "67eb5b8c-b441-4bf6-ba09-bd341f68f3c5", "metadata": {}, "source": [ "***\n", "**Ejercicio C.1:** \n", " \n", "Hagamos un script que pregunte al usuario por una cadena de texto y te diga si esa palabra es una palabra que esté en el [diccionario de la RAE](https://dle.rae.es/) o no. Para eso podemos bajarnos el fichero ```.txt``` con todas las palabras de dicho diccionario de [este repositorio](https://github.com/JorgeDuenasLerin/diccionario-espanol-txt). Por cierto que en dicho repositorio el autor cuenta como ha obtenido dicha lista de palabras (un ejercicio de *scraping* interesante, que veremos más adelante). Si tienes problemas al visualizar las palabras que contiene ese fichero (tema tildes, etc), mira la sección [codificación de caracteres](#codificacionCaracteres)." ] }, { "cell_type": "code", "execution_count": 5, "id": "26bbd92e-96e3-41ab-9ea5-733cfd6fb135", "metadata": {}, "outputs": [], "source": [ "# Tu código aquí" ] }, { "cell_type": "markdown", "id": "d9b3ace4-3127-4be1-8405-8bf9fa42b5ae", "metadata": {}, "source": [ "***\n", "**Ejercicio C.2: (¡no resuelto!)**\n", "\n", "Modifica el ejercicio B.12 para que la palabra aleatoria sea *cualquiera* del diccionario de la RAE. Lo mismo tienes problemas con los acentos, diéresis, etc... así que habrá que tener cuidado :-)" ] }, { "cell_type": "code", "execution_count": 6, "id": "4a982bf2-c993-4999-9167-610be61e812b", "metadata": {}, "outputs": [], "source": [ "# Tu código aquí" ] }, { "cell_type": "markdown", "id": "75fd0e81-8960-4dbb-a4eb-f19696f36e83", "metadata": {}, "source": [ "***\n", "### Gestión de excepciones\n", "\n", "En el siguiente código la instrucción falla porque el fichero no existe y Python lanza una [excepción](https://docs.python.org/es/3/tutorial/errors.html):" ] }, { "cell_type": "code", "execution_count": 7, "id": "4429af57-5a8a-4033-8b68-047e6c53f8dc", "metadata": {}, "outputs": [ { "ename": "FileNotFoundError", "evalue": "[Errno 2] No such file or directory: 'ficheroQueNoExiste.txt'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[7], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m f \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mopen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mficheroQueNoExiste.txt\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mr\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/anaconda3/envs/cursoAstronomia2/lib/python3.8/site-packages/IPython/core/interactiveshell.py:284\u001b[0m, in \u001b[0;36m_modified_open\u001b[0;34m(file, *args, **kwargs)\u001b[0m\n\u001b[1;32m 277\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m file \u001b[38;5;129;01min\u001b[39;00m {\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m2\u001b[39m}:\n\u001b[1;32m 278\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 279\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIPython won\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt let you open fd=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfile\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m by default \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 280\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mas it is likely to crash IPython. If you know what you are doing, \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 281\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124myou can use builtins\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m open.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 282\u001b[0m )\n\u001b[0;32m--> 284\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mio_open\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfile\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'ficheroQueNoExiste.txt'" ] } ], "source": [ "f = open(\"ficheroQueNoExiste.txt\", \"r\")" ] }, { "cell_type": "markdown", "id": "4396472f-8407-4f62-9b4d-fa8dedd27dcf", "metadata": {}, "source": [ "Las excepciones pueden saltar por muchos motivos (problemas al leer / escribir archivos, división por ```0```, intentar acceder a una posición de una lista que no existe)... Y podemos controlar el flujo de nuestro programa por si aparece alguna excepción (especialmente en los sitios donde sospechamos que se puede producir un error. Es el caso típico del manejo de ficheros, porque puede que no se pueda crear un fichero, que el disco esté lleno, que el fichero sea de solo lectura, etc. Ejemplo para gestionar las excepciones:" ] }, { "cell_type": "code", "execution_count": 8, "id": "8f269eac-6d78-4525-aa45-00e46eb8b8b0", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Algó pasó cuando se abría el fichero\n" ] } ], "source": [ "try:\n", " f = open(\"salidas/otroFichero.txt\")\n", " try:\n", " f.write(\"Algo que quiero escribir\")\n", " except:\n", " print(\"Algo pasó cuando se escribía en el fichero\")\n", " else:\n", " print(\"Parece que salió bien\")\n", " finally:\n", " f.close()\n", "except:\n", " print(\"Algó pasó cuando se abría el fichero\")" ] }, { "cell_type": "markdown", "id": "5c95cbb1-1843-4521-96ed-c394531b959e", "metadata": {}, "source": [ "+ ```try``` es una palabra reservada que inicia un bloque donde se van a controlar posibles excepciones.\n", "+ ```except``` es una palabra reservada que indica que bloque ejecutar cuando salte una excepción.\n", "+ ```else``` es una palabra reservada que indica que bloque ejecutar cuando NO ha saltado una excepción en el ```try```.\n", "+ ```finally``` es una palabra que indica que bloque ejecutar *siempre*, ocurra o no una excepción.\n", "\n", "En el caso de manejo de archivos es importante que añadamos un ```finally``` para asegurarnos que cerraremos el fichero siempre. Si no, podemos acabar con muchos ficheros \"mal cerrados\". Y eso **no** es bueno." ] }, { "cell_type": "code", "execution_count": 9, "id": "320438d2-837b-46b3-a806-78eac7239d29", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ha ocurrido una division por 0: division by zero\n", "¡Pero el programa ha continuado!\n" ] } ], "source": [ "try: \n", " val = 7 / 0\n", "except ZeroDivisionError as err:\n", " print(f\"Ha ocurrido una division por 0: {err}\")\n", " \n", "print(\"¡Pero el programa ha continuado!\")" ] }, { "cell_type": "markdown", "id": "b2dafd7b-00a7-4edb-a4ea-abcb8c3834ae", "metadata": {}, "source": [ "En este caso hemos visto como podemos identificar cada tipo de excepción que sospechemos que puede ocurrirnos. De hecho podemos tener varios bloques ```except``` atendiendo distintas excepciones en un ```try```. " ] }, { "cell_type": "markdown", "id": "4a9deb34-50f6-481f-8120-38f390f7e4fc", "metadata": {}, "source": [ "Si quisieramos capturar *cualquier* excepción y tener información sobre la misma podemos usar en la clausula `except` la clase de la que heredan **todas** las excepciones en `Python`: `BaseException`:" ] }, { "cell_type": "code", "execution_count": 10, "id": "e9794210-9f2b-4bac-8994-b9c743cdf7bb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ha ocurrido una division por 0: division by zero\n" ] } ], "source": [ "try:\n", " val = 7 / 0\n", "except BaseException as err:\n", " print(f\"Ha ocurrido una division por 0: {err}\")" ] }, { "cell_type": "markdown", "id": "33097b6d-0a05-4614-9f18-2b1fbd551fdf", "metadata": {}, "source": [ "La gestión de excepciones puede ser [más compleja](https://docs.python.org/es/3/tutorial/errors.html).\n", "\n", "Para hacer un poco más fácil el manejo de ficheros, podemos usar la clausula ```with```:" ] }, { "cell_type": "code", "execution_count": 11, "id": "44e5aa56-864f-49bc-ba16-c0bf90141b55", "metadata": {}, "outputs": [], "source": [ "with open('salidas/miFichero.txt', 'w') as fichero:\n", " fichero.write(\"Escribiendo en el fichero\\n\")\n", " fichero.write(\"Y otra línea...\\n\")" ] }, { "cell_type": "markdown", "id": "a3ddfd3a-6266-4b67-a098-f80535b6e7a3", "metadata": {}, "source": [ "Con esta sintaxis después del bloque que inicia la palabra reservada ```with``` el fichero se cerrará correctamente." ] }, { "cell_type": "markdown", "id": "11e7dbaf-1779-4a28-87f1-63e9b13f82fa", "metadata": {}, "source": [ "### Ficheros binarios\n", "\n", "Hasta ahora hemos creado y leido ficheros de texto. Pero también podríamos manejar ficheros binarios (donde la información se guarda como `bytes`). Para muchos tipos de ficheros normalmente existen bibliotecas que nos permitirán leerlos de manera más adecuada... pero si realmente queremos escribir \"*byte* a *byte*\" un fichero, podemos hacerlo.\n", "\n", "En este ejemplo vamos a escribir una imagen muy simple en el formato [*PGM* binario](https://people.sc.fsu.edu/~jburkardt/data/pgmb/pgmb.html). Basicamente es un formato en el que se escribe de la siguiente manera:\n", "\n", "+ `P5`: Identificador del tipo de imagen\n", "+ `_`: espacio en blanco\n", "+ **Anchura** de la imagen en pixeles (en modo texto)\n", "+ `_`: espacio en blanco\n", "+ **Altura** de la imagen en pixeles (en modo texto)\n", "+ `_`: espacio en blanco\n", "+ **Máximo** valor del pixel (color blanco) (en modo texto)\n", "+ `_`: espacio en blanco\n", "+ Una lista de *bytes* de tamaño **anchura** x **altura** con los valores de los píxeles de la imagen." ] }, { "cell_type": "code", "execution_count": 12, "id": "cad23b0e-e624-4e70-9ede-01c807bbbcbb", "metadata": {}, "outputs": [], "source": [ "informacion = 'P5 9 9 255 '\n", "\n", "filas = []\n", "filas.append( [0,0,0,0,255,0,0,0,0] )\n", "filas.append( [0,0,0,0,255,0,0,0,0] )\n", "filas.append( [0,0,100,0,255,0,0,0,0] )\n", "filas.append( [0,0,0,0,255,0,0,0,0] )\n", "filas.append( [255,255,255,255,255,255,255,255,255] )\n", "filas.append( [0,0,0,0,255,0,0,0,0] )\n", "filas.append( [0,0,0,0,255,0,0,0,0] )\n", "filas.append( [0,0,0,0,255,0,0,0,0] )\n", "filas.append( [0,0,0,0,255,0,0,0,0] )\n", "\n", "\n", "\n", "fichero = open(\"salidas/imagen.pgm\", \"wb\") # El modificador ```b``` especifica que el fichero es binario\n", "\n", "b = bytes(informacion, encoding=\"ASCII\")\n", "fichero.write(b)\n", "\n", "for f in filas:\n", " b = bytes(f)\n", " fichero.write(b)\n", "\n", "fichero.close()" ] }, { "cell_type": "markdown", "id": "015f359f-a403-4600-abb0-90d525d1ad6a", "metadata": {}, "source": [ "***\n", "**Ejercicio C.3: (no resuelto)**\n", " \n", "Modifica el ejercicio B.13 para que el fractal de Mandelbrot se guarde como una imagen de tipo ```PGM```. Tendrás que obtener una imagen más o menos así:\n", "\n", "![](./ficherosAuxiliares/fractal.png)" ] }, { "cell_type": "markdown", "id": "9c98eecc-6cd5-4b50-a00b-31f1d7adc67c", "metadata": {}, "source": [ "***\n", "**Ejercicio C.4: (no resuelto)**\n", " \n", "Modifica el ejercicio C.3 para que el fractal de Mandelbrot para añadir una condición de parada y poder pintar los puntos de fuera del conjunto de Mandelbrot de una manera más bonita. Se trata de parar la iteración cuando $|z| > 2$. En ese caso el punto no es del conjunto de Mandelbrot y podemos pintar ese pixel con el valor = al número de iteraciones que hemos hecho. Puedes consultar [esto](http://makeyourownmandelbrot.blogspot.com/2017/12/escape-condition-for-julia-and.html) para algo más de información. Tendrás que obtener una imagen más o menos así:\n", "\n", "![](./ficherosAuxiliares/fractalGris.png)" ] }, { "cell_type": "markdown", "id": "baf5ebb1-d013-4346-b15a-2e0a705538e8", "metadata": {}, "source": [ "### Otras operaciones con ficheros\n", "\n", "Exites otras operaciones que pueden resultar de interés para operar con ficheros, como por ejemplo comprobar si un fichero existe, su tamaño, crear carpetas, renombrarlos, etc. Veamos algunos ejemplos:" ] }, { "cell_type": "code", "execution_count": 13, "id": "c98e3cfb-6b37-44b2-9c63-3bb988c96300", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n", "False\n" ] } ], "source": [ "import os.path\n", "\n", "print(os.path.exists(\"ficherosAuxiliares/fractal.png\")) # Comprobamos que un fichero existe\n", "\n", "print(os.path.exists(\"unFicheroQueNoExiste\"))" ] }, { "cell_type": "markdown", "id": "2c994185-a54d-4aa4-bb15-dec51f99c4c1", "metadata": {}, "source": [ "También podemos usar la biblioteca ```pathlib``` ([enlace](https://docs.python.org/3/library/pathlib.html)):" ] }, { "cell_type": "code", "execution_count": 14, "id": "6c3f7d79-b267-4986-b03d-d38175054d59", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "from pathlib import Path\n", "\n", "pfractal = Path('ficherosAuxiliares/fractal.png')\n", "\n", "print(pfractal.exists()) # Otra manera de saber si existe" ] }, { "cell_type": "code", "execution_count": 15, "id": "7e2246c7-1ca1-4dc5-9a15-5e41588a22d6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n", "False\n", "True\n" ] } ], "source": [ "directorio = Path('ficherosAuxiliares')\n", "\n", "print(directorio.exists())\n", "\n", "print(directorio.is_file()) # Para saber si es un fichero\n", "\n", "print(directorio.is_dir()) # Para saber si es un directorio" ] }, { "cell_type": "code", "execution_count": 16, "id": "8025e047-4178-4c1b-932b-b118b2c22760", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/home/zerjillo/MEGA/cursoAstronomia/notebooks/ficherosAuxiliares/fractal.png\n" ] } ], "source": [ "print(pfractal.resolve()) # Obtener la ruta absoluta del fichero" ] }, { "cell_type": "code", "execution_count": 17, "id": "841606c0-6061-428d-bcea-0656d8307103", "metadata": {}, "outputs": [], "source": [ "nuevoDirectorio = Path(\"salidas/nuevoDirectorio\")\n", "Path.mkdir(nuevoDirectorio) # Para crear un directorio" ] }, { "cell_type": "code", "execution_count": 18, "id": "d4a8c053-d1b7-4797-b8b0-c3221f9256b6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "PosixPath('salidas/otroDirectorio')" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nuevoNombre = Path(\"salidas/otroDirectorio\")\n", "nuevoDirectorio.rename(nuevoNombre)" ] }, { "cell_type": "code", "execution_count": 19, "id": "cc188a9e-e661-4a43-bd9a-4e3a6c5b857b", "metadata": {}, "outputs": [], "source": [ "Path.rmdir(nuevoNombre) # Para borrar un directorio" ] }, { "cell_type": "code", "execution_count": 20, "id": "1b6e6dee-51af-410c-a22a-cae943910c68", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'salidas/fractalCopiado.png'" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import shutil # Para copiar un fichero\n", "\n", "shutil.copyfile('ficherosAuxiliares/fractal.png', 'salidas/fractalCopiado.png')" ] }, { "cell_type": "code", "execution_count": 21, "id": "9c8df888-d2c9-473a-add9-eef741e6d1fd", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ficherosAuxiliares/fractal2.png\n", "ficherosAuxiliares/fractal.png\n", "ficherosAuxiliares/mueveMotor.py\n", "ficherosAuxiliares/ESP32_motor_real.jpg\n", "ficherosAuxiliares/portadaWebScraping.jpg\n", "ficherosAuxiliares/AccelStepper.py\n", "ficherosAuxiliares/INDI_kstars_03.jpg\n", "ficherosAuxiliares/fractalGris.png\n", "ficherosAuxiliares/moduloGPS.jpg\n", "ficherosAuxiliares/webScrapingAstronomia.pdf\n", "ficherosAuxiliares/ocultacionTriton.png.svg\n", "ficherosAuxiliares/ocultacionTritonAnotada.png\n", "ficherosAuxiliares/data_cube.jpg\n", "ficherosAuxiliares/ESP32_led.jpg\n", "ficherosAuxiliares/miPrograma.py\n", "ficherosAuxiliares/main.py\n", "ficherosAuxiliares/controlDispositivosIndi.pdf\n", "ficherosAuxiliares/INDI_kstars_02.jpg\n", "ficherosAuxiliares/.ipynb_checkpoints\n", "ficherosAuxiliares/the-spectral-data-cube.png\n", "ficherosAuxiliares/ESP32.jpg\n", "ficherosAuxiliares/ocultacionTriton.png\n", "ficherosAuxiliares/portadaCurso.jpg\n", "ficherosAuxiliares/AstronomiaPython.pdf\n", "ficherosAuxiliares/portadaINDI.jpg\n", "ficherosAuxiliares/ejemploArgsparser.py\n", "ficherosAuxiliares/INDI_kstars_01.jpg\n", "ficherosAuxiliares/ESP32_led_real.jpg\n", "ficherosAuxiliares/stacking-images.jpg\n" ] } ], "source": [ "directorio = Path('ficherosAuxiliares')\n", "\n", "for hijo in directorio.iterdir(): # Iteramos por todos los ficheros (y directorios) de un directorio\n", " print(hijo)" ] }, { "cell_type": "markdown", "id": "c09a472b-bed2-46fe-b34d-ac8b16dd4587", "metadata": {}, "source": [ "***\n", "**Ejercicio C.5:**\n", "\n", "Lista todos los ficheros del directorio ```ficherosAuxiliares``` que tengan una extension ```.jpg``` o ```.png```." ] }, { "cell_type": "code", "execution_count": 22, "id": "c5a22b72-cdbf-49bf-b8da-c40087212c6d", "metadata": {}, "outputs": [], "source": [ "# Tu código aquí" ] }, { "cell_type": "markdown", "id": "8a19ff7a-ffed-4861-b828-34dd32d74036", "metadata": {}, "source": [ "***\n", "\n", "### Codificación de caracteres en los ficheros\n", "\n", "La [codificación de caracteres](https://es.wikipedia.org/wiki/Codificaci%C3%B3n_de_caracteres) es el método que permite asignar caracteres (de un alfabeto concreto) a los códigos numéricos que realmente utiliza nuestro ordenador. Históricamente ha habido varias codificaciones de caracteres. Las primeras solo permitían usar caracteres que entendería un angloparlante, mientras que en los últimos años existen codificaciones (como [Unicode](https://es.wikipedia.org/wiki/Unicode)) que permiten representar cualquier caracter de cualquier lengua.\n", "\n", "En los sistemas operativos tipo UNIX (Linux, MacOs, etc) la codificación por defecto es la variante UTF-8 de Unicode. Sin embargo en Windows es posible que el sistema utilice una codificación distinta con lo que al acceder a determinados ficheros de texto los caracteres \"especiales\" (tildes, ñ, diéresis, etc.) pueden no visualizarse bien. Para esos casos en algunas operaciones con ficheros es importante especificar la codificación que debe usarse cuando abrimos el fichero. Eso lo podemos hacer con el parámetro opcional `encoding`:" ] }, { "cell_type": "code", "execution_count": 23, "id": "3bef1075-0142-43ad-b432-0e92bdc40849", "metadata": {}, "outputs": [], "source": [ "f = open(\"salidas/miFichero.txt\", \"r\", encoding=\"utf-8\")" ] }, { "cell_type": "markdown", "id": "0c9c2a15-2215-490b-bc3a-30d6f2697ec7", "metadata": {}, "source": [ "Buscando un poco puedes encontrar [más información al respecto](https://www.adamsmith.haus/python/answers/how-to-open-a-file-with-utf-8-encoding-in-python)." ] }, { "cell_type": "markdown", "id": "fa988022-2bf0-4f14-8454-d6820c07a3ff", "metadata": {}, "source": [ "## Ejecución de programas ```Python``` fuera de ```JupyterLab```\n", "\n", "Ejecutar un programa o script de Python es muy sencillo. Dicho programa debe estar grabado en un fichero con extensión ```.py```. Por ejemplo tenemos el fichero ```miPrograma.py``` ([enlace](./ficherosAuxiliares/miPrograma.py)) con el siguiente código:" ] }, { "cell_type": "code", "execution_count": 24, "id": "8f9dddbc-7fba-4867-b555-94181dd509df", "metadata": {}, "outputs": [ { "name": "stdin", "output_type": "stream", "text": [ "¿Cómo te llamas? Zerjillo\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Encantado de conocerte Zerjillo\n" ] } ], "source": [ "nombre = input(\"¿Cómo te llamas? \")\n", "\n", "print(f\"Encantado de conocerte {nombre}\")" ] }, { "cell_type": "markdown", "id": "ec001edf-9101-4c98-92fe-8057a7e7b014", "metadata": {}, "source": [ "Para ejecutar ese programa fuera de JupyterLab solo tenemos que abrir un ```prompt``` de ```Anaconda``` y con el entorno activado (```conda activate cursoAstronomia```) para asegurarnos que se ejecuta la versión correcta de ```python``` y que tenemos todas las bibliotecas que hemos instalado ejecutamos la orden:\n", "\n", "```bash\n", " > python miPrograma.py\n", "```\n", "\n", "Y el programa debe ejecutarse sin problemas." ] }, { "cell_type": "markdown", "id": "33f4092d-0828-402d-bb3c-9e95cf8c7925", "metadata": {}, "source": [ "Si necesitamos pasarle parámetros al programa se puede hacer de varias maneras, pero mi recomenación es utilizar una biblioteca de parseo de parámetros como por ejemplo [```argparse```](https://docs.python.org/3/library/argparse.html). Podéis encontrar un [tutorial al respecto](https://docs.python.org/es/3.8/howto/argparse.html). Aquí solo mostraremos un [pequeño ejemplo](./ficherosAuxiliares/ejemploArgsparser.py):\n", "\n", "```python\n", "import argparse\n", "\n", "parser = argparse.ArgumentParser()\n", "parser.add_argument(\"echo\")\n", "\n", "args = parser.parse_args()\n", "\n", "print(args.echo)\n", "```" ] }, { "cell_type": "markdown", "id": "e0a61d4e-3f5c-404f-bc6b-df332538b59b", "metadata": {}, "source": [ "El ```import``` nos permite usar el módulo. ```parser``` será nuestro objeto parseador, al cual le añadimos un argumento posible que se llama ```echo```. El método ```parse_args()``` ejecuta el pareador con todos los argumentos que se hayan pasado y ya podemos acceder a ellos como si fueran propiedades del objeto ```args``` (```args.echo```). Si ejecutamos dicho script desde la línea de comandos:\n", "\n", "```bash\n", " > python ejemploArgsparser.py\n", "```\n", "\n", "Se quejará de que hay que pasarle un argumento llamado ```echo```. Si llamamos al programa:\n", "\n", "```bash\n", " > python ejemploArgsparser.py LALALA\n", "```\n", "\n", "comprobaremos que efectivamente se parsea uno de los argumentos (el primero) y se asigna a ```args.echo```, por lo que el programa imprime en la salida ```LALALA```." ] }, { "cell_type": "markdown", "id": "6d761651-32a5-49e9-b3d1-2ff5d14686f3", "metadata": {}, "source": [ "**Iconitos y Windows:** Si somos usuarios de Windows y *necesitamos* tener un iconito que al hacer doble click se nos ejecute nuestro programa podemos hacerlo, pero hay que hacer un poco de \"magia negra\". Podéis consultar los siguientes enlaces:\n", "\n", "+ [Windows Shortcut to Run Python Script in Anaconda Command Prompt](https://stackoverflow.com/questions/42602024/windows-shortcut-to-run-python-script-in-anaconda-command-prompt)\n", "+ [Building a Windows Shortcut with Python](https://pbpython.com/windows-shortcut.html)\n", "+ [10 lines of code, create a Windows desktop shortcut with Python!](https://pythonmana.com/2021/12/202112192312362065.html)" ] }, { "cell_type": "markdown", "id": "36258b45-7fe7-4a36-b9d7-544815cdf55e", "metadata": {}, "source": [ "## Ejecución de programas externos\n", "\n", "En ocasiones ya existen programas o utilidades que hacen algo muy bien y no tiene sentido reinventar la rueda y programar esas utilidades desde 0 en ```Python```. Lo que podemos hacer es llamar a dichas utilidades *desde* nuestro propio programa. Por ejemplo, si tenemos instaladas las utilidades de [ImageMagick](https://imagemagick.org), que nos permiten convertir ficheros de imagen entre distintos formatos, modificar las imágenes, etc desde la línea de comandos podemos hacer uso de dichas utilidades desde nuestro script sin tener que instalar nada más.\n", "\n", "Por ejemplo, si ejecuto:\n", "\n", "```bash\n", " > convert ficherosAuxiliares/fractal2.png -resize 25% ficherosAuxiliares/fractal2.jpg\n", "```\n", "\n", "Consigo que *ImageMagick* cree un fichero ```fractal2.jpg``` con formato ```JPEG``` a un cuarto del tamaño original a partir de una imagen ```fractal2.png``` en formato ```PNG```.\n", "\n", "Desde nuestro script podemos conseguir lo mismo:" ] }, { "cell_type": "code", "execution_count": 25, "id": "cecd89b7-7682-4dca-ac28-40c2bfa6ed63", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import os\n", "\n", "os.system(\"convert ficherosAuxiliares/fractal2.png -resize 25% salidas/fractal2.jpg\")" ] }, { "cell_type": "markdown", "id": "d2a8b495-e4d5-4e46-8cad-cf2e64c8c6ba", "metadata": {}, "source": [ "Incluso podemos lanzar programas que tengan interfaz de usuario:" ] }, { "cell_type": "code", "execution_count": 26, "id": "09f3c5cc-3a58-49e0-a6e1-80299b75409c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import os\n", "\n", "os.system(\"firefox\")" ] }, { "cell_type": "markdown", "id": "2999fcc9-b118-4e8c-8be7-b8abb98cc64e", "metadata": {}, "source": [ "Es mejor práctica usar el módulo ```subprocess```:" ] }, { "cell_type": "code", "execution_count": 27, "id": "1337a24f-9248-47f4-a22d-b235f5f6d829", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "CompletedProcess(args=['convert', 'ficherosAuxiliares/fractal2.png', '-resize', '25%', 'salidas/fractal2.jpg'], returncode=0)" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import subprocess\n", "\n", "subprocess.run([\"convert\", \"ficherosAuxiliares/fractal2.png\", \"-resize\", \"25%\", \"salidas/fractal2.jpg\"])" ] }, { "cell_type": "markdown", "id": "b2b1b837-010a-43b0-ab7f-756dd245cdc5", "metadata": {}, "source": [ "Algunos enlaces al respecto:\n", "\n", "+ [Ejecutando comandos de Shell con Python](https://pharos.sh/ejecutando-comandos-de-shell-con-python/)\n", "+ [subprocess – Creación y comunicación con procesos](https://recursospython.com/guias-y-manuales/subprocess-creacion-y-comunicacion-con-procesos/)" ] }, { "cell_type": "markdown", "id": "fbd16639-1305-4402-917e-4506b134c4f9", "metadata": {}, "source": [ "***\n", "**Ejercicio C.6:**\n", "\n", "Transforma con el comando externo ```convert``` de *ImageMagick* todas las imagenes ```.jpg``` y ```.png``` que haya en el directorio ```ficherosAuxiliares``` haciéndolas en doble de grandes y cuyo nombre de archivo sea el nombre original añadiéndole ```_doble```. Por ejemplo, el fichero ```fractal.png``` deberá llamarse ```fractal_doble.png```. Los ficheros copiados deberán grabarse en la carpeta ```salidas```." ] }, { "cell_type": "code", "execution_count": 28, "id": "2e77dba7-d8d4-472f-b5b1-88153118dee2", "metadata": {}, "outputs": [], "source": [ "# Tu código aqui" ] }, { "cell_type": "markdown", "id": "e368e095-3f8f-4b97-80d1-8be8837f4955", "metadata": {}, "source": [ "***\n", "**Ejercicio C.7: (no resuelto)**\n", "\n", "Haz un programa que te diga paso a paso como solucionar el juego de las [Torres de Hanói](https://es.wikipedia.org/wiki/Torres_de_Han%C3%B3i). Usando la [recursividad](https://entrenamiento-python-basico.readthedocs.io/es/latest/leccion5/funciones_recursivas.html) la solución puede ser muy escueta." ] }, { "cell_type": "markdown", "id": "f71675ac-b477-4bf6-856a-dc5e0f74f730", "metadata": {}, "source": [ "***\n", "**Ejercicio C.8: (no resuelto)**\n", "\n", "Crea un script para generar una lista de `n` números aleatorios entre `0` y `100000000`. Dicha lista debe poder grabarse en un fichero que se llame `numeros.txt`. Crea una función que permita leer dicho fichero de vuelta a una lista en memoria." ] }, { "cell_type": "markdown", "id": "509e9cc6-ee3e-4499-925b-96fc67c8f012", "metadata": {}, "source": [ "***\n", "**Ejercicio C.9: (no resuelto)**\n", "\n", "Ordenar una lista de números no es especialmente complejo. De hecho existen muchos métodos para ordenarla. Investiga como funciona el [algoritmo de ordenación](http://lwh.free.fr/pages/algo/tri/tri_es.htm) de burbuja, selección, inserción, quicksort... Programa cada uno de los algoritmos y ejecutalo sobre una lista de números aleatorios grande. Mide el tiempo que tarda cada algoritmo e imprímelo en pantalla." ] }, { "cell_type": "markdown", "id": "954b3dcd-36d3-4878-b2df-2811538ec738", "metadata": {}, "source": [ "***\n", "**Ejercicio C.10: (no resuelto)**\n", "\n", "Modifique las funciones del ejercicio anterior para que admitan como parámetro la función de comparación de manera que se puedan ordenar las listas siguiendo un criterio distinto (de mayor a menor, de menor a mayor) o incluso con datos que no sean numéricos y que, por defecto, no puedan compararse con los operadores típicos `>`, `<`, etc." ] }, { "cell_type": "markdown", "id": "9b334e0e-7c71-46b1-bee0-e7e3b570a97d", "metadata": {}, "source": [ "***\n", "**Ejercicio C.11: (no resuelto)**\n", " \n", "Supongamos que tenemos una función (del estilo a los objetos `Polinomio` que hemos hecho en ejercicios anteriores). Supongamos también que no sabemos resolver el problema de encontrar sus ceros analíticamente. Haz una función a la que le pases un objeto `Polinomio` y que mediante aproximaciones sucesivas sea capaz de decirte el punto `x`en el que la función vale `0`." ] }, { "cell_type": "markdown", "id": "1a5647e9-e974-48cc-a16e-3c62f7c62be1", "metadata": {}, "source": [ "***\n", "**Ejercicio C.12: (no resuelto)**\n", " \n", "Modifica el ejercicio anterio para encontrar por aproximaciones sucesivas un mínimo local de una función que le pasemos." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.16" } }, "nbformat": 4, "nbformat_minor": 5 }