Question

À quoi servent __ init __. py dans un répertoire source Python?

Était-ce utile?

La solution

Auparavant, il faisait partie intégrante d’un package ( old, pre -3.3 "Paquet standard" & ; pas version plus récente 3.3+ " ; espace de nommage " ).

Voici la documentation.

  

Python définit deux types de packages, les packages standard et les packages d’espaces de noms. Les packages standard sont des packages traditionnels tels qu'ils existaient dans Python 3.2 et versions antérieures. Un paquet standard est généralement implémenté en tant que répertoire contenant un fichier __ init __. Py . Lorsqu'un package standard est importé, ce fichier __ init __. Py est exécuté de manière implicite, et les objets qu'il définit sont liés à des noms situés dans l'espace de noms du package. Le fichier __ init __. Py peut contenir le même code Python que tout autre module, et Python ajoutera des attributs supplémentaires au module lors de son importation.

Mais cliquez simplement sur le lien, il contient un exemple, des informations supplémentaires et une explication des packages d'espaces de nommage, le type de packages sans __ init __. py .

Autres conseils

Les fichiers nommés __ init __. py sont utilisés pour marquer les répertoires sur disque en tant que répertoires de package Python. Si vous avez les fichiers

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

et mydir est sur votre chemin, vous pouvez importer le code dans module.py en tant que

import spam.module

ou

from spam import module

Si vous supprimez le fichier __ init __. py , Python ne recherchera plus de sous-modules dans ce répertoire. Par conséquent, toute tentative d'importation du module échouera.

Le fichier __ init __. py est généralement vide, mais peut être utilisé pour exporter des parties sélectionnées du package sous un nom plus pratique, des fonctions de maintenance, etc. Dans l'exemple ci-dessus, vous pouvez accéder au contenu du module init sous la forme

.
import spam

Basé sur this

Outre le libellé d'un répertoire en tant que package Python et la définition de __ all __ , __ init __. py vous permet de définir toute variable au niveau du package. Cela est souvent pratique si un paquet définit quelque chose qui sera importé fréquemment, à la manière d'une API. Ce modèle favorise l’adhérence à l’appartement Pythonic "mieux que l’imbrication" philosophie.

Un exemple

Voici un exemple tiré de l'un de mes projets, dans lequel j'importe fréquemment un sessionsmaker appelé Session pour interagir avec ma base de données. J'ai écrit une " base de données " package avec quelques modules:

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

Mon __ init __. py contient le code suivant:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

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

Puisque je définis ici Session , je peux démarrer une nouvelle session en utilisant la syntaxe ci-dessous. Ce code serait le même que celui exécuté de l'intérieur ou de l'extérieur de la "base de données". répertoire du package.

from database import Session
session = Session()

Bien sûr, ceci est un petit avantage - l’alternative serait de définir Session dans un nouveau fichier du type "" create_session.py "" dans mon package de base de données et démarrez de nouvelles sessions avec:

from database.create_session import Session
session = Session()

Lectures supplémentaires

Il existe un fil reddit assez intéressant couvrant les utilisations appropriées de __ init __. py ici:

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

L’opinion majoritaire semble être que les fichiers __ init __. py doivent être très minces pour éviter de violer le code "explicite, c'est mieux que implicite". philosophie.

Il y a 2 raisons principales pour __ init __. py

  1. Par souci de commodité, les autres utilisateurs n'auront pas besoin de connaître l'emplacement exact de vos fonctions dans la hiérarchie de vos packages.

    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
    

    alors les autres peuvent appeler add () par

    from your_package import add
    

    sans connaître fichier1, comme

    from your_package.file1 import add
    
  2. Si vous souhaitez que quelque chose soit initialisé; par exemple, la journalisation (qui doit être placée au niveau supérieur):

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

Le fichier __ init __. py permet à Python de traiter les répertoires qui le contiennent en tant que modules.

De plus, il s’agit du premier fichier chargé dans un module. Vous pouvez donc l’utiliser pour exécuter le code que vous souhaitez exécuter à chaque chargement d’un module ou spécifier les sous-modules à exporter.

Depuis Python 3.3, __ init __. py n'est plus nécessaire pour définir les répertoires en tant que packages Python importables.

Vérifiez PEP 420: paquets d'espace de nom implicite :

  

Prise en charge native des répertoires de paquetages ne nécessitant pas de fichier marqueur __ init __. py et pouvant s'étendre automatiquement sur plusieurs segments de chemin d'accès (inspirés de diverses approches tierces des paquets d'espace de nommage, comme décrit dans PEP 420 )

Voici le 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

références:
https://docs.python.org/3 /whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Est-ce que __init__.py n'est pas requis pour les packages dans Python 3?

En Python, la définition du paquet est très simple. Comme Java, la structure hiérarchique et la structure de répertoires sont identiques. Mais vous devez avoir __ init __. Py dans un paquet. Je vais expliquer le fichier __ init __. Py avec l'exemple ci-dessous:

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 peut être vide, tant qu'il existe. Cela indique que le répertoire doit être considéré comme un paquet. Bien entendu, __ init __. Py peut également définir le contenu approprié.

Si nous ajoutons une fonction dans module_n1:

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

Après avoir exécuté:

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

function_X in module_n1 

Ensuite, nous avons suivi le paquetage hiérarchique et appelé module_n1 la fonction. Nous pouvons utiliser __ init __. Py dans subPackage_b comme ceci:

__all__ = ['module_n2', 'module_n3']

Après avoir exécuté:

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

Par conséquent, en utilisant * importing, le module est soumis au contenu __ init __. py .

Bien que Python fonctionne sans un fichier __ init __. py , vous devez tout de même en inclure un.

Il spécifie qu'un paquet doit être traité comme un module, donc incluez-le (même s'il est vide).

Dans certains cas, vous pouvez utiliser un fichier __ init __. py :

Imaginez que vous ayez la structure de fichier suivante:

main_methods 
    |- methods.py

Et methods.py contenait ceci:

def foo():
    return 'foo'

Pour utiliser foo () , vous devez disposer de l’un des éléments suivants:

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

Peut-être avez-vous besoin (ou souhaitez-vous) de conserver methods.py dans main_methods (runtimes / dependencies par exemple) mais vous ne souhaitez importer que main_methods .

Si vous avez changé le nom de methods.py en __ init __. py , vous pouvez utiliser foo () en important simplement . main_methods :

import main_methods
print(main_methods.foo()) # Prints 'foo'

Cela fonctionne car __ init __. py est traité comme une partie du package.

Certains paquets Python le font réellement. Par exemple, JSON , où importer json importe réellement __ init __. py à partir du package json ( voir la structure du fichier de paquet ici ):

  

Code source: Lib / json / __ init __. py

__ init __. py considérera le répertoire dans lequel il se trouve comme un module chargeable.

Pour les personnes qui préfèrent lire du code, j'ajoute le commentaire de de l'alchimiste à deux bits ici.

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

Cela facilite l’importation d’autres fichiers Python. Lorsque vous avez placé ce fichier dans un répertoire (par exemple, stuff) contenant d’autres fichiers py, vous pouvez effectuer une opération semblable à une opération import stuff.other.

root\
    stuff\
         other.py

    morestuff\
         another.py

Sans ce __ init __. py dans le répertoire, vous ne pouvez pas importer other.py, car Python ne sait pas où se trouve le code source du matériel et est incapable de le reconnaître en tant que package. .

Un fichier __ init __. py facilite les importations. Lorsqu'un __ init __. Py est présent dans un package, la fonction a () peut être importée du fichier b.py comme suit:

from b import a

Sans cela, vous ne pouvez pas importer directement. Vous devez modifier le chemin du système:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top