Introducción
Si estás escribiendo un programa más grande, realmente no quieres organizarlo como una gran colección de archivos independientes en el nivel superior. Esta sección introduce el concepto de un paquete.
This tutorial is from open-source community. Access the source code
💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí
Si estás escribiendo un programa más grande, realmente no quieres organizarlo como una gran colección de archivos independientes en el nivel superior. Esta sección introduce el concepto de un paquete.
Cualquier archivo fuente de Python es un módulo.
## foo.py
def grok(a):
...
def spam(b):
...
Una declaración import
carga y ejecuta un módulo.
## program.py
import foo
a = foo.grok(2)
b = foo.spam('Hello')
...
Para colecciones más grandes de código, es común organizar los módulos en un paquete.
## De esto
pcost.py
report.py
fileparse.py
## A esto
porty/
__init__.py
pcost.py
report.py
fileparse.py
Elegís un nombre y creáis un directorio de nivel superior. porty
en el ejemplo anterior (claramente, elegir este nombre es el primer paso más importante).
Agregá un archivo __init__.py
al directorio. Puede estar vacío.
Colocá tus archivos fuente en el directorio.
Un paquete sirve como un espacio de nombres para las importaciones.
Esto significa que ahora hay importaciones de múltiples niveles.
import porty.report
port = porty.report.read_portfolio('portfolio.csv')
Hay otras variaciones de las declaraciones de importación.
from porty import report
port = report.read_portfolio('portfolio.csv')
from porty.report import read_portfolio
port = read_portfolio('portfolio.csv')
Este enfoque tiene dos problemas principales.
Entonces, básicamente todo se rompe. Pero, aparte de eso, funciona.
Las importaciones entre archivos en el mismo paquete ahora deben incluir el nombre del paquete en la importación. Recuerda la estructura.
porty/
__init__.py
pcost.py
report.py
fileparse.py
Ejemplo de importación modificada.
from porty import fileparse
def read_portfolio(filename):
return fileparse.parse_csv(...)
Todas las importaciones son absolutas, no relativas.
import fileparse ## SE ROMPE. fileparse no se encuentra
...
En lugar de usar directamente el nombre del paquete, puedes usar .
para referirte al paquete actual.
from. import fileparse
def read_portfolio(filename):
return fileparse.parse_csv(...)
Sintaxis:
from. import modname
Esto facilita renombrar el paquete.
Ejecutar un submódulo de un paquete como un script principal se rompe.
$ python porty/pcost.py ## SE ROMPE
...
Razón: Estás ejecutando Python en un solo archivo y Python no ve correctamente el resto de la estructura del paquete (sys.path
está incorrecto).
Todas las importaciones se rompen. Para solucionar esto, debes ejecutar tu programa de una manera diferente, usando la opción -m
.
$ python -m porty.pcost ## FUNCIONA
...
__init__.py
El propósito principal de estos archivos es unir los módulos.
Ejemplo: consolidando funciones
## porty/__init__.py
from.pcost import portfolio_cost
from.report import portfolio_report
Esto hace que los nombres aparezcan en el nivel superior al importar.
from porty import portfolio_cost
portfolio_cost('portfolio.csv')
En lugar de usar importaciones de múltiples niveles.
from porty import pcost
pcost.portfolio_cost('portfolio.csv')
Como se ha señalado, ahora debes usar -m package.module
para ejecutar scripts dentro de tu paquete.
$ python3 -m porty.pcost portfolio.csv
Hay otra alternativa: Escribe un nuevo script de nivel superior.
#!/usr/bin/env python3
## pcost.py
import porty.pcost
import sys
porty.pcost.main(sys.argv)
Este script se encuentra fuera del paquete. Por ejemplo, mirando la estructura de directorios:
pcost.py ## script de nivel superior
porty/ ## directorio del paquete
__init__.py
pcost.py
...
La organización del código y la estructura de archivos son clave para la mantenibilidad de una aplicación.
No existe un enfoque "uno para todos" para Python. Sin embargo, una estructura que funciona para muchos problemas es la siguiente.
porty-app/
README.txt
script.py ## SCRIPT
porty/
## CÓDIGO DE LIBRERÍA
__init__.py
pcost.py
report.py
fileparse.py
El nivel superior porty-app
es un contenedor para todo lo demás: documentación, scripts de nivel superior, ejemplos, etc.
Una vez más, los scripts de nivel superior (si los hay) deben existir fuera del paquete de código. Un nivel arriba.
#!/usr/bin/env python3
## porty-app/script.py
import sys
import porty
porty.report.main(sys.argv)
En este momento, tienes un directorio con varios programas:
pcost.py ## Calcula el costo de la cartera
report.py ## Genera un informe
ticker.py ## Produce un cotizador de acciones en tiempo real
Hay una variedad de módulos de soporte con otras funcionalidades:
stock.py ## Clase Stock
portfolio.py ## Clase Portfolio
fileparse.py ## Análisis de CSV
tableformat.py ## Tablas formateadas
follow.py ## Sigue un archivo de registro
typedproperty.py ## Propiedades de clase tipadas
En este ejercicio, vamos a limpiar el código y ponerlo en un paquete común.
Crea un directorio llamado porty/
y coloca todos los archivos de Python anteriores en él. Además, crea un archivo __init__.py
vacío y colócalo en el directorio. Deberías tener un directorio de archivos como este:
porty/
__init__.py
fileparse.py
follow.py
pcost.py
portfolio.py
report.py
stock.py
tableformat.py
ticker.py
typedproperty.py
Elimina el archivo __pycache__
que se encuentra en tu directorio. Este contiene módulos de Python pre-compilados de antes. Queremos comenzar de nuevo.
Intenta importar algunos de los módulos del paquete:
>>> import porty.report
>>> import porty.pcost
>>> import porty.ticker
Si estas importaciones fallan, ve al archivo apropiado y corrige las importaciones de módulos para incluir una importación relativa al paquete. Por ejemplo, una declaración como import fileparse
podría cambiar a la siguiente:
## report.py
from. import fileparse
...
Si tienes una declaración como from fileparse import parse_csv
, cambia el código a lo siguiente:
## report.py
from.fileparse import parse_csv
...
Poner todo tu código en un "paquete" no es a menudo suficiente para una aplicación. A veces hay archivos de soporte, documentación, scripts y otras cosas. Estos archivos deben existir FUERA del directorio porty/
que creaste anteriormente.
Crea un nuevo directorio llamado porty-app
. Mueve el directorio porty
que creaste en el Ejercicio 9.1 a ese directorio. Copia los archivos de prueba portfolio.csv
y prices.csv
en este directorio. Además, crea un archivo README.txt
con información sobre ti mismo. Tu código ahora debería estar organizado como sigue:
porty-app/
portfolio.csv
prices.csv
README.txt
porty/
__init__.py
fileparse.py
follow.py
pcost.py
portfolio.py
report.py
stock.py
tableformat.py
ticker.py
typedproperty.py
Para ejecutar tu código, debes asegurarte de trabajar en el directorio principal porty-app/
. Por ejemplo, desde la terminal:
$ cd porty-app
$ python3
>>> import porty.report
>>>
Intenta ejecutar algunos de tus scripts anteriores como un programa principal:
$ cd porty-app
$ python3 -m porty.report portfolio.csv prices.csv txt
Name Shares Price Change
---------- ---------- ---------- ----------
AA 100 9.22 -22.98
IBM 50 106.28 15.18
CAT 150 35.46 -47.98
MSFT 200 20.89 -30.34
GE 95 13.48 -26.89
MSFT 50 20.89 -44.21
IBM 100 106.28 35.84
$
Usar el comando python -m
a menudo es un poco extraño. Es posible que desees escribir un script de nivel superior que simplemente gestione las particularidades de los paquetes. Crea un script print-report.py
que genere el informe anterior:
#!/usr/bin/env python3
## print-report.py
import sys
from porty.report import main
main(sys.argv)
Coloca este script en el directorio principal porty-app/
. Asegúrate de que puedas ejecutarlo en esa ubicación:
$ cd porty-app
$ python3 print-report.py portfolio.csv prices.csv txt
Name Shares Price Change
---------- ---------- ---------- ----------
AA 100 9.22 -22.98
IBM 50 106.28 15.18
CAT 150 35.46 -47.98
MSFT 200 20.89 -30.34
GE 95 13.48 -26.89
MSFT 50 20.89 -44.21
IBM 100 106.28 35.84
$
Tu código final ahora debería estar estructurado de algo así:
porty-app/
portfolio.csv
prices.csv
print-report.py
README.txt
porty/
__init__.py
fileparse.py
follow.py
pcost.py
portfolio.py
report.py
stock.py
tableformat.py
ticker.py
typedproperty.py
¡Felicidades! Has completado el laboratorio de Paquetes. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.