APIs publiques et privées¶
En Python, tout est public. Pour permettre aux développeurs de savoir sur quels composants ils peuvent compter, Flower déclare une API publique. Les composants qui font partie de l’API publique peuvent être utilisés. Les modifications apportées à l’API publique sont annoncées dans les notes de mise à jour et sont soumises à des politiques de dépréciation.
Tout ce qui ne fait pas partie de l’API publique fait partie de l’API privée. Même si Python permet d’y accéder, le code utilisateur ne doit jamais utiliser ces composants. Les API privées peuvent être modifiées à tout moment, même dans les versions de correctifs.
Comment déterminer si un composant fait partie de l’API publique ou non ? Facile :
Utiliser la documentation de référence de l’API Flower <ref-api/flwr.html>`_
Tout ce qui est listé dans la documentation de référence fait partie de l’API publique. Ce document explique comment les administrateurs de Flower définissent l’API publique et comment vous pouvez déterminer si un composant fait partie de l’API publique ou non en lisant le code source de Flower.
API publique de Flower¶
Flower dispose d’une API publique bien définie. Examinons-la plus en détail.
Important
Chaque composant accessible en suivant récursivement __init__.__all__ à partir du paquet racine (flwr) fait partie de l’API publique.
Si vous voulez déterminer si un composant (classe/fonction/générateur/…) fait partie de l’API publique ou non, vous devez commencer à la racine du paquet flwr. Utilisons tree -L 1 -d src/py/flwr pour regarder les sous-paquets Python contenus dans flwr :
flwr
├── cli
├── client
├── common
├── proto
├── server
└── simulation
Comparez cela avec la définition de all__'' dans la racine ``src/py/flwr/__init__.py :
# From `flwr/__init__.py`
__all__ = [
"client",
"common",
"server",
"simulation",
]
Vous pouvez voir que flwr a six sous-ensembles (cli, client, common, proto, server, simulation), mais seulement quatre d’entre eux sont « exportés » via __all__ (client, common, server, simulation).
Qu’est-ce que cela signifie ? Cela signifie que client, common, server et simulation font partie de l’API publique, mais cli et proto ne le sont pas. Les sous-ensembles flwr de cli et proto sont des APIs privées. Une API privée peut changer complètement d’une version à la suivante (même dans les mises à jour de patch). Elle peut changer de manière brisante, elle peut être renommée (par exemple, flwr.cli pourrait être renommé en flwr.command) et elle peut même être supprimée complètement.
Par conséquent, en tant qu’utilisateur de Flower :
from flwr import client✅ D’accord, vous importez une API publique.from flwr import proto❌ Non recommandé, vous importez une API privée.
Et qu’en est-il des composants qui sont plus profondément enracinés dans la hiérarchie ? Regardons les stratégies Flower pour voir un autre modèle typique. Les stratégies Flower comme FedAvg sont souvent importées à l’aide de from flwr.server.strategy import FedAvg. Regardez src/py/flwr/server/strategy/__init__.py :
from .fedavg import FedAvg as FedAvg
# ... more imports
__all__ = [
"FedAvg",
# ... more exports
]
Ce qui est notable ici, c’est que toutes les stratégies sont implémentées dans des modules dédiés (par exemple, fedavg.py). Dans __init__.py, nous importons les composants dont nous voulons faire partie de l’API publique et puis exportons-les via __all__. Notez que nous exportons le composant lui-même (par exemple, la classe FedAvg), mais pas le module dans lequel il est défini (par exemple, fedavg.py). Cela permet de déplacer la définition de FedAvg dans un autre module (ou même dans un sous-ensemble) sans briser l’API publique (à condition que nous mettions à jour le chemin d’importation dans __init__.py).
Par conséquent :
from flwr.server.strategy import FedAvg✅ D’accord, vous importez une classe qui fait partie de l’API publique.from flwr.server.strategy import fedavg❌ Non recommandé, vous importez un module privé.
Cette approche est également mise en œuvre dans les outils qui construisent automatiquement des documents de référence API.
API publique Flower des paquets privés¶
Nous utilisons également cela pour définir l’API publique des sous-ensembles privés. Publique, dans ce contexte, signifie l’API que les autres flwr sous-ensembles devraient utiliser. Par exemple, flwr.superlink.grid est un sous-ensemble privé (il n’est pas ré-exporté via src/py/flwr/superlink/__init__.py).
Malgré tout, le sous-ensemble privé flwr.superlink.grid définit une « API publique » en utilisant __all__ dans src/py/flwr/superlink/grid/__init__.py:
from .grpc_grid import GrpcGrid
from .inmemory_grid import InMemoryGrid
__all__ = [
"GrpcGrid",
"InMemoryGrid",
]
La partie intéressante est que les deux GrpcGrid et InMemoryGrid sont jamais utilisés par les utilisateurs du cadre Flower, mais uniquement par d’autres parties du codebase du cadre Flower. Ces autres parties du codebase importent, par exemple, InMemoryGrid à l’aide de from flwr.superlink.grid import InMemoryGrid (c’est-à-dire que le InMemoryGrid est exporté via __all__), et non from flwr.superlink.grid.inmemory_grid import InMemoryGrid (inmemory_grid.py est le module contenant la définition réelle de la classe InMemoryGrid).
Cela se fait parce que flwr.superlink.grid définit une interface publique pour les sous-ensembles flwr. Cela permet aux propriétaires du code flwr.superlink.grid de refacturer l’ensemble sans briser d’autres utilisateurs internes flwr.