# La librería estándar La librería estándar se refiere a todas las utilidades que un lenguaje de programación trae consigo. Los lenguajes de programación, a parte de aportar la propia funcionalidad del lenguaje en sí mismo que simplemente sería la ejecución del código fuente que se le indique, suelen incluir funcionalidades que no están necesariamente relacionadas con ese proceso. El motivo de esto es facilitar el uso del lenguaje para las labores más comunes, incluyendo el código necesario para realizarlas sin necesitar añadidos externos. En lenguajes de programación de dominio específico la librería estándar suele contemplar muchos casos de ese dominio concreto. Por ejemplo, el lenguaje de programación Julia, aunque esté diseñado con el objetivo de ser un lenguaje válido para cualquier uso, su área de trabajo se centra en el entorno científico. Es por eso que incluye en su librería estándar paquetes de álgebra lineal, estadística y otros. Existen muchas diferentes aproximaciones a la librería estándar. Algunos lenguajes las mantienen extremadamente reducidas con el fin de que la implementación del lenguaje sea más liviana, con la contrapartida de forzar a quien los use a tener que utilizar herramientas externas o a desarrollarlas. Python es un lenguaje de propósito general con una extensísima librería estándar. Esto dificulta la selección de apartados a mostrar en este capítulo, pero facilita la programación de cualquier aplicación en éste lenguaje. Los paquetes estándar de python facilitan la lectura de infinidad de tipos de fichero, la conversión y el tratamiento de datos, el acceso a la red, la ejecución concurrente, etc. por lo que librería estándar es más que suficiente para muchas aplicaciones y no se requiere añadir módulos externos. Conocer la librería estándar y ser capaz de buscar en ella los paquetes que necesites te facilitará mucho la tarea, evitando, por un lado, que dediques tiempo a desarrollar funcionalidades que el propio lenguaje ya aporta y, por otro, que instales paquetes externos que no necesitas. Todos los apartados aquí listados están extremadamente bien documentados en la página oficial de la documentación de python y en la propia ayuda. Eso sí, tendrás que importarlos para poder leer la ayuda, pero ya sabes cómo se hace. A continuación se recogen los módulos más interesantes, aunque en función del proyecto puede que necesites algún otro. Puedes acceder al listado completo en la página oficial de la documentación[^stdlibdoc]. [^stdlibdoc]: ## Interfaz al sistema operativo: `os` Ya definimos previamente el concepto *interfaz* como superficie de contacto entre dos entidades. Esta librería facilita la interacción entre python y el sistema operativo. La comunicación con el sistema operativo es primordial para cualquier lenguaje de programación de uso general, ya que es necesario tener la capacidad de hacer peticiones directas al sistema operativo. Por ejemplo, cambiar de directorio actual para facilitar la inclusión rutas relativas en el programa, resolver rutas a directorios y un largo etc. En capítulos previos hemos hablado de las diferencias entre sistemas operativos. Esta librería, además, facilita el trabajo para esos casos. Por ejemplo, que el separador de directorios en UNIX es `/` y en Windows `\`, si quisiéramos programar una aplicación multiplataforma, nos encontraríamos con problemas. Sin embargo, el módulo `os.path` dispone de herramientas para gestionar las rutas de los directorios por nosotros, por ejemplo, la variable `os.path.sep` (copiada en `os.sep` por abreviar), guarda el valor del separador del sistema en el que se esté ejecutando la aplicación: `/` en UNIX y `\` en Windows. Este paquete es muy interesante para desarrollar código portable entre las diferentes plataformas. ## Funciones relacionadas con el intérprete: `sys` Aunque el nombre de este módulo suene complicado, su uso principal es el de acceder a funcionalidades que el propio python controla. Concretamente, se usa sobre todo para la recepción de argumentos de entrada al programa principal, la redirección de entradas y salidas del programa y la terminación del programa. ### Salida forzada: `sys.exit()` Para salir de forma abrupta del programa y terminar su ejecución, python facilita la función `sys.exit()`. Al ejecutarla la ### *Standard streams*: `sys.stdin`, `sys.stdout` y `sys.stderr` Cuando se trabaja en programas que funcionan en la terminal se pueden describir tres vías de comunicación con el usuario: 1. El teclado: de donde se obtiene lo que el usuario teclee mediante la función `input`. 2. La pantalla: a donde se escribe al ejecutar la función `print`. 3. Y la salida de errores: Una salida especial para los fallos, similar a la anterior, pero que se diferencia para poder hacer un tratamiento distinto y porque tiene ciertas peculiaridades distintas. Los mensajes de error de excepciones se envían aquí. Estas tres vías se conocen comúnmente como entrada estándar (*standard input*), `stdin`, salida estándar (*standard output*), `stdout`, y error estándar (*standard error*), `stderr`. Este concepto responde al nombre de *standard streams* y es una abstracción de los dispositivos físicos que antiguamente se utilizaban para comunicarse con una computadora. Hoy en día, estos tres *streams* son una abstracción de esa infraestructura y se comportan como simples ficheros de lectura en el primer caso y de escritura en los otros dos. Los diferentes sistemas operativos los implementan a su modo, pero desde el interior de python son simplemente ficheros abiertos, como si se hubiese ejecutado la función `open` en ellos y ellos se encargan de leer o escribir a la vía de interacción con el usuario correspondiente. Es decir, en realidad `print`, `input`, etc. son únicamente funciones que facilitan la labor de escribir manualmente en estos *streams*: ``` python >>> import sys >>> chars = sys.stdout.write("Hola\n") Hola >>> chars # Recoge el número de caracteres escritos 5 ``` La realidad es que estos *streams* dan una flexibilidad adicional muy interesante. Como son únicamente variables de ficheros abiertos pueden cerrarse y sustituirse por otros, permitiéndote redireccionar la entrada o la salida de un programa a un fichero. El siguiente ejemplo redirecciona la salida de errores a un fichero llamado `exceptions.txt` y trata de mostrar una variable que no está definida. Python en lugar de mostrar el mensaje de una excepción, la escribe en el fichero al que se ha redireccionado la salida: ``` python >>> sys.stderr = open("exceptions.txt", "w") >>> aasda # No muestra el mensaje de error >>> >>> with open("exceptions.txt") as f: ... f.read() # Muestra el contenido del archivo ... 'Traceback (most recent call last):\n File "", line 1, in \ \nNameError: name \'aasda\' is not defined\n' ``` ### Argumentos de entrada: `sys.argv` Es posible añadir argumentos de entrada a la ejecución de los programas. Piensa en el propio programa llamado python, al ejecutarlo en la shell de sistema se le pueden mandar diferentes opciones que, por ejemplo, digan qué módulo debe ejecutar: ``` bash python test.py ``` Para la shell de sistema, todo lo que se escriba después de la primera palabra es considerado un argumento de entrada. Cuando se ejecutan nuestros programas escritos en python, es posible también enviarles argumentos de entrada: ``` bash python test.py argumento1 argumento2 ... ``` Lo que el python reciba después del nombre del módulo a ejecutar lo considerará argumentos de entrada de nuestro módulo y nos lo ordenará y dejará disponible en la variable `sys.argv`, una lista de todos los argumentos de entrada. Si muestras el contenido de la variable en la REPL, te responderá `['']` ya que la REPL se ejecuta sin argumentos. Sin embargo, si creas un módulo y le añades este contenido: ``` python import sys print(sys.argv) ``` Verás que se imprime una lista con el nombre del archivo en su primer elemento. Si ejecutas el módulo desde la shell de sistema añadiéndole argumentos de entrada: ``` bash python modulo.py arg1 arg2 arg3 ``` La lista `sys.argv` recibirá todos, siempre a modo de string. Los argumentos de entrada son extremadamente interesantes para permitir que los programas sean configurables por quien los use sin necesidad de tener que editar el código fuente, cosa que nunca debería ser necesaria a menos que exista un error en éste o quiera añadirse una funcionalidad. ## Procesamiento de argumentos de entrada: `argparse` Como la variable `sys.argv` entrega los argumentos de entrada tal y como los recibe y no comprueba si son coherentes, python dispone de una librería adicional para estas labores. El módulo `argparse` permite definir qué tipo de argumentos de entrada y opciones tiene tu programa y qué reglas deben seguir. Además, facilita la creación de ayudas como la que se muestra cuando ejecutas `python -h` o `pip -h` en la shell de tu sistema. Es una librería bastante compleja con infinidad de opciones que es mejor que leas en la propia documentación cuando necesites utilizarla. ## Expresiones regulares: `re` Las expresiones regulares (*regular expression*, también conocidas como *regexp* y *regex*) son secuencias de caracteres que describen un patrón de búsqueda. En python se soportan mediante el módulo `re` de la librería estándar. ## Matemáticas y estadística: `math` y `statistics` El módulo `math` soporta gran cantidad de operaciones matemáticas avanzadas para coma flotante. En él puedes encontrar logaritmos, raíces, etc. El módulo `statistics` soporta estadística básica como medias, medianas, desviación típica, etc. Ambos módulos tienen mucho interés ya que python se usa extensivamente en el análisis de datos. Aunque tiene librerías de terceros mucho más adecuadas para esta labor, para proyectos pequeños puede que sea suficiente con estos módulos. ## Protocolos de internet: `urllib` `urllib` es un conjunto de paquetes que permiten seguir URLs o enlaces, principalmente para HTTP y su versión segura HTTPs. Soporta cookies, redirecciones, autenticación básica, etc. El siguiente ejemplo te muestra cómo descargar el primer boceto del estándar del protocolo HTTP de la página web del IETF. Recordando los apartados previos, fíjate en el uso de la sentencia `with` y en el uso de los corchetes para obtener un número limitado de caracteres de la recién decodificada respuesta. ``` python >>> from urllib.request import urlopen >>> with urlopen("https://tools.ietf.org/rfc/rfc2068.txt") as resp: ... print( resp.read().decode("utf-8")[:1750] ) ... ' Network Working Group R. Fielding Request for Comments: 2068 UC Irvine Category: Standards Track J. Gettys J. Mogul DEC H. Frystyk T. Berners-Lee MIT/LCS January 1997 Hypertext Transfer Protocol -- HTTP/1.1 Status of this Memo This document specifies an Internet standards track protocol for the Internet community, and requests discussion and suggestions for improvements. Please refer to the current edition of the "Internet Official Protocol Standards" (STD 1) for the standardization state and status of this protocol. Distribution of this memo is unlimited. Abstract The Hypertext Transfer Protocol (HTTP) is an application-level protocol for distributed, collaborative, hypermedia information systems. It is a generic, stateless, object-oriented protocol which can be used for many tasks, such as name servers and distributed object management systems, through extension of its request methods. A feature of HTTP is the typing and negotiation of data representation, allowing systems to be built independently of the data being transferred. HTTP has been in use by the World-Wide Web global information initiative since 1990. This specification defines the protocol referred to as "HTTP/1.1". ' >>> ``` ## Fechas y horas: `datetime` `datetime`, que ya ha aparecido anteriormente, es un módulo para gestión de fecha y hora. `datetime` soporta gran cantidad de operaciones y tipos de dato. Entre ellos los `timedeltas`, diferencias temporales que te permiten sumar y restar fechas con facilidad con los operadores habituales. Con las facilidades de `datetime`, es poco probable que necesites importar una librería de gestión de fecha y hora independiente. ## Procesamiento de ficheros: `json` y `sqlite3` Python habilita gran cantidad de procesadores de formatos de fichero, los dos que se lista en este apartado tienen especial interés. El primer módulo, `json`, sirve para manipular datos en formato JSON. Sus dos funciones principales `dumps` y `loads` vuelcan o cargan datos de JSON a diccionarios o listas en una sola orden debido que la propia estructura de JSON está formada por parejas clave valor o listas de valores ordenadas por índices. Esta es la razón por la que en muchas ocasiones se utilizan ficheros de formato JSON para intercambiar información entre aplicaciones de python: su lectura y escritura es extremadamente sencilla. El segundo módulo, `sqlite3`, facilita el acceso a ficheros en formato SQLite3, un formato binario con una interfaz de acceso que permite consultas SQL. El módulo `sqlite3` es capaz de convertir las tablas que SQLite3 retorna a estructuras de python de forma transparente y cómoda por lo que es un aliado interesante para aplicaciones que requieren una base de datos pequeña y resiliente. ## Aritmética de coma flotante decimal: `decimal` En el apartado sobre datos tratamos la complejidad de los números de coma flotante y que su representación binaria puede dar lugar a problemas. Este módulo de aritmética decimal aporta una solución rigurosa a este problema con el fin de facilitar el uso de python en entornos que requieren precisión estricta que incluso puede requerir cumplir con normativas, como puede ser la banca. La documentación del módulo muestra un par de ejemplos muy interesantes usando la clase `Decimal` aportada por este. Se adjuntan a continuación para que los estudies y los disecciones en busca de las diferencias con el uso de los números de coma flotante normales: ``` python >>> from decimal import * >>> round(Decimal('0.70') * Decimal('1.05'), 2) Decimal('0.74') >>> round(.70 * 1.05, 2) 0.73 >>> Decimal('1.00') % Decimal('.10') Decimal('0.00') >>> 1.00 % 0.10 0.09999999999999995 >>> sum([Decimal('0.1')]*10) == Decimal('1.0') True >>> sum([0.1]*10) == 1.0 False ``` ## Lo que has aprendido Más que aprender, en este apartado has sobrevolado la librería estándar de python desde la distancia y te has parado a observar qué problemas comunes ya están resueltos en python. La realidad es que la librería estándar es mucho más extensa que lo listado en este apartado, pero aquí se han mencionado los módulos que más frecuentemente se suelen usar en entornos normales y algunos otros que tienen interés a la hora de afianzar conocimiento que has obtenido en capítulos previos, como es el caso del módulo `decimal`. Este capítulo empieza a mostrarte el interés de programar en python y las posibilidades que tienes con él, únicamente con la librería estándar. En el próximo verás la cantidad de funcionalidad adicional que le puedes añadir con un par de librerías escritas por terceros. Sirva también este capítulo como recordatorio de lo extensa que es la librería estándar de python. En el futuro, cuando tengas intención de buscar una librería para resolver un problema que te despista de trabajar en la funcionalidad principal de tu aplicación, empieza por la librería estándar.