python file - A cosa serve __init__.py?




example packages (10)

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


Answers

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 .


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)
    

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.


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


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?


__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
>>> 

Fa parte di un pacchetto. Ecco la documentazione.

I file __init__.py sono necessari per far sì che Python tratti le directory come contenenti i pacchetti; questo viene fatto per evitare che le directory con un nome comune, come la string , nascondano involontariamente moduli validi che si verificano in seguito (più in profondità) sul percorso di ricerca del modulo. Nel caso più semplice, __init__.py può essere solo un file vuoto, ma può anche eseguire il codice di inizializzazione per il pacchetto o impostare la variabile __all__ , descritta più avanti.


Il file __init__.py consente a Python di trattare le directory che lo contengono come moduli.

Inoltre, questo è il primo file da caricare in un modulo, quindi è possibile utilizzarlo per eseguire il codice che si desidera eseguire ogni volta che viene caricato un modulo o specificare i sottomoduli da esportare.


# -** coding: utf-8 -*-
import os
import traceback

print '\n\n'

def start():
    address = "/home/ubuntu/Desktop"
    try:
        Folders = []
        Id = 1
        for item in os.listdir(address):
            endaddress = address + "/" + item
            Folders.append({'Id': Id, 'TopId': 0, 'Name': item, 'Address': endaddress })
            Id += 1         

            state = 0
            for item2 in os.listdir(endaddress):
                state = 1
            if state == 1: 
                Id = FolderToList(endaddress, Id, Id - 1, Folders)
        return Folders
    except:
        print "___________________________ ERROR ___________________________\n" + traceback.format_exc()

def FolderToList(address, Id, TopId, Folders):
    for item in os.listdir(address):
        endaddress = address + "/" + item
        Folders.append({'Id': Id, 'TopId': TopId, 'Name': item, 'Address': endaddress })
        Id += 1

        state = 0
        for item in os.listdir(endaddress):
            state = 1
        if state == 1: 
            Id = FolderToList(endaddress, Id, Id - 1, Folders)
    return Id

print start()




python module