10. Pequeño paseo por la Biblioteca Estándar¶
10.1. Interfaz al sistema operativo¶
El módulo os
provee docenas de funciones para interactuar con el sistema operativo:
>>> import os
>>> os.getcwd() # Return the current working directory
'C:\\Python38'
>>> os.chdir('/server/accesslogs') # Change current working directory
>>> os.system('mkdir today') # Run the command mkdir in the system shell
0
Asegúrate de usar el estilo import os
en lugar de from os import *
. Esto evitará que os.open()
oculte a la función integrada open()
, que trabaja bastante diferente.
Las funciones integradas dir()
y help()
son útiles como ayudas interactivas para trabajar con módulos grandes como os
:
>>> import os
>>> dir(os)
<returns a list of all module functions>
>>> help(os)
<returns an extensive manual page created from the module's docstrings>
Para tareas diarias de administración de archivos y directorios, el módulo shutil
provee una interfaz de más alto nivel que es más fácil de usar:
>>> import shutil
>>> shutil.copyfile('data.db', 'archive.db')
'archive.db'
>>> shutil.move('/build/executables', 'installdir')
'installdir'
10.2. Comodines de archivos¶
El módulo glob
provee una función para hacer listas de archivos a partir de búsquedas con comodines en directorios:
>>> import glob
>>> glob.glob('*.py')
['primes.py', 'random.py', 'quote.py']
10.3. Argumentos de linea de órdenes¶
Los programas frecuentemente necesitan procesar argumentos de linea de órdenes. Estos argumentos se almacenan en el atributo argv del módulo sys
como una lista. Por ejemplo, la siguiente salida resulta de ejecutar python demo.py uno dos tres
en la línea de órdenes:
>>> import sys
>>> print(sys.argv)
['demo.py', 'one', 'two', 'three']
El modulo argparse
provee un mecanismo más sofisticado para procesar argumentos recibidos vía línea de comandos. El siguiente script extrae uno o más nombres de archivos y un número opcional de líneas para mostrar:
import argparse
parser = argparse.ArgumentParser(prog = 'top',
description = 'Show top lines from each file')
parser.add_argument('filenames', nargs='+')
parser.add_argument('-l', '--lines', type=int, default=10)
args = parser.parse_args()
print(args)
Cuando se ejecuta por línea de comandos haciendo python top.py --lines=5 alpha.txt beta.txt
, el script establece args.lines
a 5
y args.filenames
a ['alpha.txt', 'beta.txt']
.
10.4. Redirigir la salida de error y finalización del programa¶
El módulo sys
también tiene atributos para stdin, stdout, y stderr. Este último es útil para emitir mensajes de alerta y error para que se vean incluso cuando se haya redirigido stdout:
>>> sys.stderr.write('Warning, log file not found starting a new one\n')
Warning, log file not found starting a new one
La forma más directa de terminar un programa es usar sys.exit()
.
10.5. Coincidencia en patrones de cadenas¶
El módulo re
provee herramientas de expresiones regulares para un procesamiento avanzado de cadenas. Para manipulación y coincidencias complejas, las expresiones regulares ofrecen soluciones concisas y optimizadas:
>>> import re
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
>>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'
Cuando se necesita algo más sencillo solamente, se prefieren los métodos de las cadenas porque son más fáciles de leer y depurar:
>>> 'tea for too'.replace('too', 'two')
'tea for two'
10.6. Matemática¶
El módulo math
permite el acceso a las funciones de la biblioteca C subyacente para la matemática de punto flotante:
>>> import math
>>> math.cos(math.pi / 4)
0.70710678118654757
>>> math.log(1024, 2)
10.0
El módulo random
provee herramientas para realizar selecciones al azar:
>>> import random
>>> random.choice(['apple', 'pear', 'banana'])
'apple'
>>> random.sample(range(100), 10) # sampling without replacement
[30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
>>> random.random() # random float
0.17970987693706186
>>> random.randrange(6) # random integer chosen from range(6)
4
El módulo statistics
calcula propiedades de estadística básica (la media, mediana, varianza, etc) de datos numéricos:
>>> import statistics
>>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
>>> statistics.mean(data)
1.6071428571428572
>>> statistics.median(data)
1.25
>>> statistics.variance(data)
1.3720238095238095
El proyecto SciPy <https://scipy.org> tiene muchos otros módulos para cálculos numéricos.
10.7. Acceso a Internet¶
Hay varios módulos para acceder a Internet y procesar sus protocolos. Dos de los más simples son urllib.request
para traer data de URLs y smtplib
para mandar correos:
>>> from urllib.request import urlopen
>>> with urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl') as response:
... for line in response:
... line = line.decode('utf-8') # Decoding the binary data to text.
... if 'EST' in line or 'EDT' in line: # look for Eastern Time
... print(line)
<BR>Nov. 25, 09:43:32 PM EST
>>> import smtplib
>>> server = smtplib.SMTP('localhost')
>>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
... """To: jcaesar@example.org
... From: soothsayer@example.org
...
... Beware the Ides of March.
... """)
>>> server.quit()
(Notá que el segundo ejemplo necesita un servidor de correo corriendo en la máquina local)
10.8. Fechas y tiempos¶
El módulo datetime
ofrece clases para gestionar fechas y tiempos tanto de manera simple como compleja. Aunque soporta aritmética sobre fechas y tiempos, el foco de la implementación es en la extracción eficiente de partes para gestionarlas o formatear la salida. El módulo también soporta objetos que son conscientes de la zona horaria.
>>> # dates are easily constructed and formatted
>>> from datetime import date
>>> now = date.today()
>>> now
datetime.date(2003, 12, 2)
>>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.")
'12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.'
>>> # dates support calendar arithmetic
>>> birthday = date(1964, 7, 31)
>>> age = now - birthday
>>> age.days
14368
10.9. Compresión de datos¶
Los formatos para archivar y comprimir datos se soportan directamente con los módulos: zlib
, gzip
, bz2
, lzma
, zipfile
y tarfile
.
>>> import zlib
>>> s = b'witch which has which witches wrist watch'
>>> len(s)
41
>>> t = zlib.compress(s)
>>> len(t)
37
>>> zlib.decompress(t)
b'witch which has which witches wrist watch'
>>> zlib.crc32(s)
226805979
10.10. Medición de rendimiento¶
Algunos usuarios de Python desarrollan un profundo interés en saber el rendimiento relativo de las diferentes soluciones al mismo problema. Python provee una herramienta de medición que responde esas preguntas inmediatamente.
Por ejemplo, puede ser tentador usar la característica de empaquetado y desempaquetado de las tuplas en lugar de la solución tradicional para intercambiar argumentos. El módulo timeit
muestra rápidamente una modesta ventaja de rendimiento:
>>> from timeit import Timer
>>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
0.57535828626024577
>>> Timer('a,b = b,a', 'a=1; b=2').timeit()
0.54962537085770791
En contraste con el fino nivel de medición del módulo timeit
, los módulos profile
y pstats
proveen herramientas para identificar secciones críticas de tiempo en bloques de código más grandes.
10.11. Control de calidad¶
Una forma para desarrollar software de alta calidad es escribir pruebas para cada función mientras se la desarrolla, y correr esas pruebas frecuentemente durante el proceso de desarrollo.
El módulo doctest
provee una herramienta para revisar un módulo y validar las pruebas integradas en las cadenas de documentación (o docstring) del programa. La construcción de las pruebas es tan sencillo como cortar y pegar una ejecución típica junto con sus resultados en los docstrings. Esto mejora la documentación al proveer al usuario un ejemplo y permite que el módulo doctest se asegure que el código permanece fiel a la documentación:
def average(values):
"""Computes the arithmetic mean of a list of numbers.
>>> print(average([20, 30, 70]))
40.0
"""
return sum(values) / len(values)
import doctest
doctest.testmod() # automatically validate the embedded tests
El módulo unittest
necesita más esfuerzo que el módulo doctest
, pero permite que se mantenga en un archivo separado un conjunto más comprensivo de pruebas:
import unittest
class TestStatisticalFunctions(unittest.TestCase):
def test_average(self):
self.assertEqual(average([20, 30, 70]), 40.0)
self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
with self.assertRaises(ZeroDivisionError):
average([])
with self.assertRaises(TypeError):
average(20, 30, 70)
unittest.main() # Calling from the command line invokes all tests
10.12. Las pilas incluidas¶
Python tiene una filosofía de «pilas incluidas». Esto se ve mejor en las capacidades robustas y sofisticadas de sus paquetes más grandes. Por ejemplo:
Los módulo
xmlrpc.client
yxmlrpc.server
convierten una implementación de la llamada a un procedimiento en una tarea casi trivial. A pesar de los nombres de los nombres, no se necesita ningún conocimiento o manejo de archivos XML.El paquete
email
es una biblioteca para administrar mensajes de correo electrónico, incluidos MIME y otros documentos de mensajes basados en RFC 2822. A diferencia desmtplib
ypoplib
que realmente envían y reciben mensajes, el paquete de correo electrónico tiene un conjunto de herramientas completo para crear o decodificar estructuras de mensajes complejas (incluidos los archivos adjuntos) y para implementar protocolos de codificación y encabezado de Internet.El paquete
json
proporciona un sólido soporte para analizar este popular formato de intercambio de datos. El módulocsv
admite la lectura y escritura directa de archivos en formato de valor separado por comas, comúnmente compatible con bases de datos y hojas de cálculo. El procesamiento XML es compatible con los paquetesxml.etree.ElementTree
,xml.dom
yxml.sax
. Juntos, estos módulos y paquetes simplifican en gran medida el intercambio de datos entre aplicaciones de Python y otras herramientas.El módulo
sqlite3
es un wrapper para la biblioteca de bases de datos SQLite, proporcionando una base de datos persistente que se puede actualizar y acceder mediante una sintaxis SQL ligeramente no estándar.La internacionalización es compatible con una serie de módulos, incluyendo
gettext
,locale
, y el paquetecodecs
.