__all__ en Python

Hiten Kanwar 30 novembre 2021
__all__ en Python

Au fur et à mesure que nous approfondissons les packages et les modules, nous pourrions rencontrer la variable __all__ définie dans différents fichiers _init_.py.

Les fichiers __init__.py sont les fichiers qui permettent à Python de traiter les répertoires comme des packages contenant. Ce fichier empêche les répertoires portant des noms similaires, tels que des chaînes, de masquer les modules valides qui pourraient apparaître ultérieurement sur un chemin de recherche de module.

Dans le cas le plus simple, __init__.py peut être un fichier vide, mais il peut également exécuter le code d’initialisation du package ou définir la variable __all__.

Par conséquent, le __init__.py peut déclarer les variables __all__ pour un package.

Une liste des objets publics de ce module est donnée dans la variable __all__. Il est interprété par le import *. Cette variable remplace la valeur par défaut consistant à masquer tout ce qui commence par un trait de soulignement de l’espace de noms donné.

Par exemple,

__all__ = ["a", "b"]
c = 5
a = 10


def b():
    return "b"

Maintenant, nous importons cela dans le code suivant.

from sample import *

print(a)  # will work fine
print(b)  # will work fine
print(c)  # will generate an error

Dans l’exemple ci-dessus, nous avons utilisé import * pour importer tous les objets publics du fichier sample.py vers ce fichier. Cela signifie que ce fichier importera et supportera tous les objets publics du fichier sample.py.

Les objets a et b seront importés et le nouveau code fonctionnera parfaitement là où ces objets sont utilisés. Le problème se pose dans l’utilisation du troisième objet, c. Cet objet n’est jamais importé dans le nouveau fichier car ce n’est pas un objet public, car il ne fait pas partie de la variable __all__. Cette partie du code va donc générer une erreur.

Il existe une alternative à cela. Par défaut, Python se chargera d’exporter tous les noms qui ne commencent pas par un trait de soulignement _. Et l’on pourrait certainement s’appuyer sur ce mécanisme. Dans la bibliothèque standard Python, certains packages s’appuient sur cela, mais pour ce faire, ils aliasent leurs importations, par exemple, os en tant que _os, sys en tant que _sys, etc.

L’utilisation de la convention _ est plus pratique car elle supprime la redondance de nommer les noms à plusieurs reprises. Mais cela ajoute la redondance pour les importations (si vous en avez beaucoup), et il est plus facile d’oublier de le faire de manière cohérente.

De nombreux packages de la bibliothèque standard utilisent __all__. Il est logique d’utiliser la convention de préfixe _ à la place de __all__ lorsque vous êtes encore en mode de développement précoce, que vous n’avez pas d’utilisateurs et que vous peaufinez constamment votre API. Il y a peut-être quelques utilisateurs, mais l’un a des tests unitaires couvrant l’API et toujours activement mis à jour et ajouté à l’API et peaufiner le développement.