create - python__init__ file example




A cosa serve__init__.py? (8)

Ci sono 2 ragioni principali per __init__.py

  1. Per comodità: gli altri utenti non dovranno conoscere la posizione esatta delle funzioni nella gerarchia dei pacchetti.

    your_package/
      __init__.py
      file1.py/
      file2.py/
        ...
      fileN.py
    
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    
    # in file1.py
    def add():
        pass
    

    quindi altri possono chiamare add () per

    from your_package import add
    

    senza conoscere file1, come

    from your_package.file1 import add
    
  2. Se vuoi che qualcosa venga inizializzato; per esempio, logging (che dovrebbe essere messo nel livello più alto):

    import logging.config
    logging.config.dictConfig(Your_logging_config)
    

Cos'è __init__.py in una directory di origine Python?


Da Python 3.3, __init__.py non è più richiesto per definire le directory come pacchetti Python importabili.

Verifica PEP 420: Pacchetti spazio dei nomi impliciti :

Supporto nativo per le directory dei pacchetti che non richiedono i file di marcatori __init__.py e possono estendersi automaticamente su più segmenti di percorso (ispirati da vari approcci di terze parti ai pacchetti dello spazio dei nomi, come descritto in PEP 420 )

Ecco il test:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

Riferimenti:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
__Init__.py non è richiesto per i pacchetti in Python 3?


Facilita l'importazione di altri file python. Quando hai inserito questo file in una directory (ad esempio qualcosa) contenente altri file py, puoi fare qualcosa come import stuff.other.

root\
    stuff\
         other.py

    morestuff\
         another.py

Senza questo __init__.py all'interno della directory, non è possibile importare other.py, perché Python non sa dove si trova il codice sorgente di roba e non riesce a riconoscerlo come pacchetto.


I file denominati __init__.py vengono utilizzati per contrassegnare le directory su disco come directory di pacchetti Python. Se hai i file

mydir/spam/__init__.py
mydir/spam/module.py

e mydir è sul tuo percorso, puoi importare il codice in module.py as

import spam.module

o

from spam import module

Se rimuovi il file __init__.py , Python non cercherà più i sottomoduli all'interno della directory, quindi i tentativi di importazione del modulo falliranno.

Il file __init__.py è in genere vuoto, ma può essere utilizzato per esportare porzioni selezionate del pacchetto con un nome più conveniente, tenere funzioni di convenienza, ecc. Dato l'esempio sopra, è possibile accedere al contenuto del modulo init come

import spam

basato su this


In Python la definizione del pacchetto è molto semplice. Come Java, la struttura gerarchica e la struttura delle directory sono le stesse. Ma devi avere __init__.py in un pacchetto. Spiegherò il file __init__.py con l'esempio seguente:

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py può essere vuoto, purché esista. Indica che la directory dovrebbe essere considerata come un pacchetto. Ovviamente, __init__.py può anche impostare il contenuto appropriato.

Se aggiungiamo una funzione in module_n1:

def function_X():
    print "function_X in module_n1"
    return

Dopo aver eseguito:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

Quindi abbiamo seguito il pacchetto di gerarchia e chiamato module_n1 la funzione. Possiamo usare __init__.py in subPackage_b in questo modo:

__all__ = ['module_n2', 'module_n3']

Dopo aver eseguito:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

Quindi usando * importando, il pacchetto del modulo è soggetto al contenuto __init__.py .


Oltre all'etichettatura di una directory come pacchetto Python e alla definizione di __all__ , __init__.py consente di definire qualsiasi variabile a livello di pacchetto. Fare ciò è spesso conveniente se un pacchetto definisce qualcosa che verrà importato frequentemente, in un modo simile all'API. Questo modello promuove l'adesione alla filosofia "piatta è meglio di nidificare" di Python.

Un esempio

Ecco un esempio di uno dei miei progetti, in cui importano spesso un sessionmaker chiamato Session per interagire con il mio database. Ho scritto un pacchetto "database" con alcuni moduli:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

Il mio __init__.py contiene il seguente codice:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

Poiché definisco Session qui, posso iniziare una nuova sessione usando la sintassi di seguito. Questo codice sarebbe lo stesso eseguito dall'interno o dall'esterno della directory del pacchetto "database".

from database import Session
session = Session()

Ovviamente, questa è una piccola comodità: l'alternativa sarebbe definire Session in un nuovo file come "create_session.py" nel mio pacchetto database e avviare nuove sessioni usando:

from database.create_session import Session
session = Session()

Ulteriori letture

C'è un interessante thread di reddit che copre gli usi appropriati di __init__.py qui:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

L'opinione della maggioranza sembra essere che i file __init__.py dovrebbero essere molto sottili per evitare di violare la filosofia "esplicita è meglio di quella implicita".


__init__.py considera la directory in cui si trova come un modulo caricabile.

Per le persone che preferiscono leggere il codice, ho inserito il commento di Alchimista di Due Bit qui.

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 

A cosa serve __init__.py?

L'uso principale di __init__.py è di inizializzare i pacchetti Python. Il modo più semplice per dimostrarlo è dare un'occhiata alla struttura di un modulo Python standard.

package/
    __init__.py
    file.py
    file2.py
    file3.py
    subpackage/
        __init__.py
        submodule1.py
        submodule2.py

Come puoi vedere nella struttura sopra l'inclusione del file __init__.py in una directory indica all'interprete Python che la directory deve essere trattata come un pacchetto Python

Cosa succede in __init__.py ?

__init__.py può essere un file vuoto ma viene spesso utilizzato per eseguire l'installazione necessaria per il pacchetto (importa cose, carica cose nel percorso, ecc.).

Una cosa comune da fare in __init__.py è importare classi, funzioni, ecc. Selezionate nel livello del pacchetto in modo che possano essere facilmente importate dal pacchetto.

Nell'esempio sopra possiamo dire che file.py ha il file di classe. Quindi, senza nulla nel nostro __init__.py importeresti con questa sintassi:

from package.file import File

Tuttavia puoi importare File nel tuo __init__.py per renderlo disponibile a livello di pacchetto:

# in your __init__.py
from file import File

# now import File from package
from package import File

Un'altra cosa da fare è a livello di pacchetto rendere disponibili sotto-pacchetti / moduli con la variabile __all__ . Quando l'interprete vede una variabile __all__ definita in un __init__.py , importa i moduli elencati nella variabile __all__ quando lo fai:

from package import *

__all__ è un elenco contenente i nomi dei moduli che si desidera importare con import *, quindi se si guarda nuovamente all'esempio precedente se si desidera importare i sottomoduli nel sottopackage, la variabile __all__ in subpackage/__init__.py sarebbe:

__all__ = ['submodule1', 'submodule2']

Con la variabile __all__ popolata in quel modo, quando esegui

from subpackage import *

importerebbe submodule1 e submodule2.

Come puoi vedere, __init__.py può essere molto utile oltre alla sua funzione primaria di indicare che una directory è un modulo.

Reference







module