Cuando comenzamos a trabajar con python para proyectos web lo primero con lo que tuvimos que lidiar fue con conseguir una buena estructura de archivos.

Como buenos principiantes buscamos estructuras template en github y otros lugares, pero todas nos quedaban demasiado grandes. Habían muchas carpetas que no entendíamos para qué servían, ¿por qué andar sacando funciones de esa manera? ¿Archivos con solo 10 líneas de código?

Sabíamos que todo tendría su razón y que esta se nos escapaba.

Poco a poco hemos ido comprendiendo en la práctica el por qué de muchas de estas estructuras estándar, también hay otras que no entendemos del todo o con las que simplemente no estamos de acuerdo (cada uno tiene sus propias necesidades).

En toda nuestra confusión por intentar entender estos conceptos más avanzados nos topamos con algo muy confuso: __init__.py

¿Qué es esto? ¿Un archivo de python que se llama igual que el constructor de clases?
¿Por qué en algunos proyectos está vacío y en otro está lleno?

En el momento de comenzar a trabajar optamos por no complicarnos y seguir para adelante sin terminar de entender a que nos enfrentábamos (esta ha sido una política interna durante casi todo el tiempo que trabajamos juntos).

__init__.py

¿Para qué sirve este archivo?
__init__.py es la manera que tiene python de inicializar paquetes, modulos o librerías. Le dice al sistema que carpetas contienen estos elementos para poder importarlos directamente desde cualquier nivel de nuestro proyecto.

Imaginemos que tenemos la siguiente estructura de archivos:


PythonRPG/
		game.py
		server.py
		models.py
		GameData/
			__init__.py
			orcos.py
			elfos.py
			escenario.py
			profesiones.py

El simple hecho de haber creado ese archivo __init__.py en mi subcarpeta GameData, aunque esté vacio, ya me permite entrar a cualquiera de mis archivos de la carpeta principal PythonRPG/ e importar alguna de las clases, métodos, objetos o variables de los archivos de GameData de la siguiente manera:

from GameData.orcos import orcAttack

como vemos, lo único que he hecho es escribir la ruta completa de la clase como si se tratase de un método al mismo nivel que el archivo en el que estoy trabajando.

¿Vemos su utilidad?

Si, nos permite estructurar nuestro proyecto de manera más ordenada, teniendo subcarpetas que nos permitan agrupar nuestras clases y métodos.

¿Es suficiente con esto?

Quizá no, y para estos casos o preferencias es que podemos jugar a rellenar ___init___.py de la siguiente manera:

from orcos import orcAttack

Esto nos permite que luego desde cualquier archivo al nivel principal de nuestro proyecto hagamos una importación directa

from GameData import orcAttack

¿Útil no?

Aún hay más.

__init__.py utiliza el magic method de python __all__

__all__ acepta una lista de archivos a su mismo nivel, por ejemplo

__all__ = [‘orcos’, ‘elfos’, ‘escenarios’]

¿Para que sirve esto?

Pues bueno, alguna vez han hecho en sus archivos principales de python un

from [libreria] import * 

Pues es de esta manera que * sabe que métodos o clases importar. En el caso presentado en el ejemplo anterior esta importación llamaría a todos los archivos exceptuando a profesiones.

Muy útil no?

__init__.py también es utilizado para inicializar elementos del programa o modulo, ya que al importar elementos de ese modulo o librería, todo el código que se encuentra en __init__.py se ejecuta de manera automática.