Curso de Python / Organizar paquetes y definir un punto de entrada
Un paquete agrupa módulos relacionados en una jerarquía. Mantener la ejecución de la aplicación dentro de main() y de un punto de entrada explícito permite importar el módulo desde otro programa sin ejecutarlo automáticamente.
Preparar la estructura de un paquete regular
Este ejemplo utiliza un paquete regular con __init__.py. Existen paquetes de espacio de nombres que pueden omitir ese archivo, pero aquí la estructura explícita ayuda a reconocer las piezas. Ejecuta las órdenes desde project, la carpeta que contiene expense_app, no desde el interior del paquete.
project/
expense_app/
__init__.py
math_tools.py
__main__.py
La organización del código en módulos explica el papel de cada archivo .py. La referencia oficial de __main__ describe el punto de entrada que utiliza Python al ejecutar un paquete.
Guardar todos los archivos y ejecutar el paquete
Guarda este contenido en expense_app/__init__.py, en UTF-8:
"""Expense calculation package."""
El archivo expense_app/math_tools.py contiene la función reutilizable:
def total(amounts):
return sum(amounts)
Guarda el punto de entrada en expense_app/__main__.py:
from .math_tools import total
def main():
print(total([3500, 8000, 2500]))
if __name__ == "__main__":
main()
Desde la carpeta project y con el entorno del proyecto seleccionado, ejecuta:
python -m expense_app
El resultado debe ser 14000. La opción -m localiza el destino mediante la búsqueda de módulos y proporciona el contexto del paquete. En macOS o Ubuntu, fuera del entorno virtual, utiliza python3 si corresponde al intérprete preparado.
Controlar la ejecución con __name__
El destino que se ejecuta como programa recibe el nombre __main__. Cuando se importa, recibe su nombre de módulo o paquete. La condición if __name__ == "__main__" utiliza esa diferencia para llamar a main únicamente al ejecutar el programa.
Las definiciones de funciones pueden permanecer en el nivel superior. Los cálculos y las modificaciones de archivos que no deben ocurrir durante una importación se realizan dentro de las funciones, cuando se las llama expresamente. Una simple importación no debería activar por sorpresa el trabajo de la aplicación.
Ejecutar directamente python expense_app/__main__.py es diferente de utilizar -m. La importación relativa from .math_tools import total necesita un contexto de paquete; ejecutar un archivo interno sin ese contexto puede producir ImportError. Mantén fijo el código y compara las órdenes y carpetas de ejecución.
La búsqueda de módulos tampoco equivale a la búsqueda de datos. Una ruta de datos relativa depende de la carpeta de trabajo. Un programa distribuible puede necesitar argumentos de ruta explícitos o recursos del paquete en lugar de asumir que siempre empieza junto a sus archivos fuente.
Comprobar por separado el comportamiento al importar
Desde project, ejecuta esta comprobación adicional:
python -c "import expense_app.__main__; print('imported')"
Debe aparecer únicamente imported. Si también aparece el total, revisa las instrucciones del nivel superior que siguen ejecutándose al importar. Comprobar el resultado del programa y la reutilización sin efectos secundarios detecta problemas diferentes.
Si cambias el nombre del paquete, actualiza tanto las rutas de importación como las órdenes de ejecución. Crear una distribución instalable añade configuración pyproject.toml, construcción e instalación de prueba: no se resuelve solo ordenando carpetas. La creación y verificación de un paquete distribuible desarrolla esas etapas.




