www tutorial standard org online modules libreria learnpython learn for course biblioteca python initialization package

python - tutorial - Agregar código a__init__.py



standard modules python (3)

Es solo una preferencia personal realmente, y tiene que ver con el diseño de sus módulos de python.

Digamos que tienes un módulo llamado erikutils . Hay dos maneras en que puede ser un módulo, ya sea que tenga un archivo llamado erikutils.py en su sys.path o que tenga un directorio llamado erikutils en su sys.path con un archivo __init__.py vacío dentro de él. Entonces digamos que tiene un grupo de módulos llamados fileutils , procutils , parseutils y quiere que esos sean submódulos bajo erikutils . Así que creas algunos archivos .py llamados fileutils.py , procutils.py y parseutils.py :

erikutils __init__.py fileutils.py procutils.py parseutils.py

Tal vez tenga algunas funciones que simplemente no pertenecen a los fileutils , procutils o parseutils . Y digamos que no tiene ganas de crear un nuevo módulo llamado miscutils . Y, le gustaría poder llamar a la función de esta manera:

erikutils.foo() erikutils.bar()

en lugar de hacer

erikutils.miscutils.foo() erikutils.miscutils.bar()

Entonces, como el módulo erikutils es un directorio, no un archivo, tenemos que definir sus funciones dentro del archivo __init__.py .

En django, el mejor ejemplo que puedo pensar es django.db.models.fields . TODAS las clases de campo django * se definen en el archivo __init__.py en el __init__.py django / db / models / fields . Supongo que lo hicieron porque no querían incluir todo en un hipotético modelo django / db / models / fields.py , por lo que lo dividieron en unos pocos submódulos ( related.py , files.py , por ejemplo) y pegaron las definiciones de campo * en el propio módulo de campos (por lo tanto, __init__.py ).

Echaré un vistazo a cómo funciona el sistema modelo en django y noté algo que no entiendo.

Sé que crea un archivo __init__.py vacío para especificar que el directorio actual es un paquete. Y que puede establecer alguna variable en __init__.py para que la importación * funcione correctamente.

Pero django agrega un montón de ... import ... declaraciones y define un grupo de clases en __init__.py . ¿Por qué? ¿Esto no solo hace que las cosas se vean desordenadas? ¿Hay alguna razón que requiera este código en __init__.py ?


Todas las importaciones en __init__.py están disponibles cuando importa el paquete (directorio) que lo contiene.

Ejemplo:

./dir/__init__.py :

import something

./test.py :

import dir # can now use dir.something

EDITAR: se olvidó de mencionar, el código en __init__.py ejecuta la primera vez que importa un módulo de ese directorio. Por lo tanto, normalmente es un buen lugar para poner cualquier código de inicialización de nivel de paquete.

EDIT2: dgrant señaló una posible confusión en mi ejemplo. En la import something __init__.py import something puede importar cualquier módulo, no necesario desde el paquete. Por ejemplo, podemos reemplazarlo por import datetime , luego en nuestro nivel superior test.py ambos fragmentos funcionarán:

import dir print dir.datetime.datetime.now()

y

import dir.some_module_in_dir print dir.datetime.datetime.now()

La línea inferior es: todos los nombres asignados en __init__.py , ya sean módulos, funciones o clases importados, están automáticamente disponibles en el espacio de nombres del paquete cada vez que importa el paquete o un módulo en el paquete.


Usar el archivo __init__.py permite hacer que la estructura interna del paquete sea invisible desde el exterior. Si la estructura interna cambia (p. Ej., Porque divide un módulo gordo en dos), solo tiene que ajustar el archivo __init__.py , pero no el código que depende del paquete. También puede hacer que partes de su paquete sean invisibles, por ejemplo, si no están listas para uso general.

Tenga en cuenta que puede usar el comando del , por lo que un __init__.py típico puede verse así:

from somemodule import some_function1, some_function2, SomeObject del somemodule

Ahora, si decides dividir somemodule el nuevo __init__.py podría ser:

from somemodule1 import some_function1, some_function2 from somemodule2 import SomeObject del somemodule1 del somemodule2

Desde el exterior, el paquete todavía se ve exactamente como antes.