Modèle parfait pour démarrer des projets Python

Modèle parfait pour démarrer des projets Python

Python est un excellent langage avec de nombreuses bibliothèques disponibles. Du jeu à l'intelligence artificielle, en passant par le back-end ou l'automatisation. Il y a toutefois un inconvénient majeur : le manque de structure et le désordre dû aux types dynamiques. Dans cet article, j'identifie tous ces problèmes et je vous propose une solution pour chacun d'entre eux. Enfin, je partage avec vous un référentiel de modèle GitHub pour démarrer vos nouveaux projets Python du bon pied et livrer du code de haute qualité en un rien de temps !

Consultez le référentiel sur : Check the GitHub repository. Laissez une étoile si le dépôt vous aide !

Introduction

En tant qu'ingénieur en apprentissage automatique, Python est l'un des outils que j'utilise au quotidien. C'est un langage expressif, rapide à écrire et il bénéficie de l'un des écosystèmes les plus riches, sans oublier que la plupart des outils pour construire de l'intelligence artificielle sont disponibles en Python. Cependant, j'identifie deux principaux inconvénients qui peuvent nuire à votre productivité et à la robustesse de votre code : le manque de structure (types dynamiques) et le manque d'outils de qualité de code intégrés.

Problème 1: Gestion des dépendances

Problème

L'installation de bibliothèques tierces est une étape essentielle dans tout projet de programmation. Mais ce n'est pas suffisant. Il devrait être possible de contrôler les versions des bibliothèques que vous utilisez et d'installer le projet avec toutes ses dépendances sur n'importe quel ordinateur. Vous souhaitez également une isolation pour éviter de mélanger les dépendances entre différents projets. En effet, si vous avez différents projets dépendant de la même bibliothèque mais avec une version différente, vous ne voulez pas qu'ils entrent en conflit les uns avec les autres.

La manière standard de résoudre ces problèmes en Python est d'utiliser Pypi (pour installer des packages) et les environnements virtuels (pour l'isolation). Le flux de travail typique est le suivant :

  1. Vous créez un dossier pour votre projet
  2. Vous créez un environnement virtuel
  3. Vous installez les dépendances avec pip
  4. Vous stockez la liste des dépendances dans un fichier requirements.txt en utilisant pip freeze

Cela vous offre :

  • Isolation : les packages installés dans l'environnement virtuel sont isolés du reste du système
  • Reproductibilité (dans une certaine mesure) : vous pouvez réinstaller toutes les dépendances lorsque vous téléchargez le projet, mais vous n'êtes pas assuré d'atteindre le même état à un autre moment

Il reste 2 problèmes :

  • Mélange de dépendances : vous obtenez un fichier requirements.txt mélangé avec vos dépendances ainsi que les packages requis par ces dépendances. Il est difficile de suivre facilement les packages dont vous dépendez réellement
  • Faible reproductibilité : vous n'êtes pas assuré d'atteindre le même état des dépendances du projet si vous réinstallez votre projet ultérieurement car pip freeze ne verrouille pas les dépendances.

Solution

Utilisez un autre gestionnaire de packages : Poetry. C'est un gestionnaire de packages et de construction moderne. Il est vraiment simple à utiliser, il vous suffit de fournir un fichier : le fichier pyproject.toml. Il résout les 2 problèmes mentionnés ci-dessus.

  • Dépendances propres : dans votre fichier pyproject.toml, vous ne spécifiez que la dépendance directe de votre projet. Elle ne sera jamais mélangée avec les dépendances d'autres packages
  • Reproductibilité forte : poetry introduit un fichier de verrouillage poetry.lock dans votre projet. Dans ce fichier, toutes les dépendances sont verrouillées à la version résolue lors de l'installation. Vous êtes assuré d'avoir le même état des dépendances pour votre projet chaque fois que vous l'installez

Problème 2: Qualité du code et CI/CD

Problème

Super, nous avons résolu le problème de gestion des dépendances ! Mais qu'en est-il de l'application de la qualité du code dans votre projet ? Avec un langage à typage statique comme Rust ou Java, le compilateur détecte de nombreux problèmes lors de la compilation. Malheureusement, nous n'avons pas cette chance avec notre cher langage à typage dynamique.

Un autre facteur important dans une bonne base de code est la cohérence. Python ne dispose pas d'un formateur de code par défaut, mais nous devons d'une certaine manière imposer de bonnes pratiques de mise en forme et idéalement, nous voulons que cela soit automatique.

Solution

Une bonne solution couvre 5 points.

1. Vérification statique des types

Python a introduit les annotations de type vers la version 3.5. Il existe d'excellents outils construits autour de cette fonctionnalité d'annotation de type. N'oubliez pas que les annotations de type ne sont pas obligatoires en Python, c'est une fonctionnalité facultative. Vous pouvez exécuter votre code même si les annotations sont incorrectes ou non respectées. Pour effectuer la vérification réelle des types et vérifier que notre code est correct au moment de la compilation, nous utiliserons Mypy. C'est un vérificateur de types statiques conçu pour Python. Si vous venez de langages à typage statique, les vérifications du compilateur vous manqueront pour détecter de nombreux bugs potentiels. Mypy vous forcera à passer un peu de temps à écrire et à respecter les annotations de type, mais ce investissement portera ses fruits plus rapidement que vous ne le pensez.

2. Formatage

Pour formater le code Python, mes outils préférés sont Black et Isort. Ils viennent avec un ensemble prédéfini de règles qui sont un excellent choix par défaut et que vous pouvez facilement personnaliser dans la configuration pyproject.toml. Black vous aidera à formater votre code, par exemple, en cassant les lignes trop longues, en imposant des retours à la ligne entre les fonctions, etc. Isort vous aidera à garder vos imports triés avec une séparation entre les dépendances intégrées à Python, les dépendances internes et les dépendances tierces. Il est préférable de le maintenir cohérent dans tous les fichiers de votre projet.

Avant/après le formatage du code Avant/après le formatage du code

3. Linting

Le linting est un autre outil de qualité du code. Il vérifie votre code par rapport à une longue liste de règles et vous indique celles que vous enfreignez. Des règles comme les variables inutilisées, les noms en double, l'héritage incorrect, ... C'est important pour la santé de votre projet. Il existe de nombreux linters disponibles tels que Pylint, Flake8, Autopep ... Personnellement, j'utilise Flake8.

4. Tests

Python dispose d'une prise en charge native des tests unitaires. Cependant, je vous encourage à utiliser Pylint qui est un outil puissant pour écrire des tests avec des fonctionnalités qui vous facilitent la vie, notamment grâce à des fixtures. Je reviendrai peut-être sur Pytest dans un autre article.

5. CI/CD

Il est fort probable que vous utilisiez un outil comme GitHub pour sauvegarder votre dépôt Git à distance. Idéalement, vous souhaitez exécuter tous vos contrôles de qualité du code avant que code soit fusionné dans votre branche principale afin d'éviter la dégradation de la base de code au fil du temps. Nous avons deux façons complémentaires de le faire :

  1. Crochets pre-commit : ce sont des scripts exécutés avant chaque commit en local, ils exécuteront tous vos outils de qualité de code et refuseront le commit si le code ne passe pas. C'est un moyen simple d'appliquer les meilleures pratiques à chaque commit.
  2. GitHub actions : ce sont des scripts exécutés automatiquement par GitHub lors de certains déclencheurs. Par exemple, lorsque vous ouvrez une pull request, GitHub construira votre code dans un conteneur et exécutera tous vos contrôles de code. Il vous empêchera de fusionner la pull request dans la branche principale si les vérifications n'ont pas réussi.

Utiliser une combinaison des deux méthodes est recommandé. En effet, les crochets pre-commit sont rapides car ils s'exécutent localement, vous n'avez pas besoin d'attendre le processus à distance de GitHub. Cependant, rien ne garantit que chaque développeur exécute les crochets pre-commit avant de pousser le code. Ainsi, avoir les GitHub actions qui vérifient votre code est la garantie ultime que tout le code fusionné sur la branche principale répond à vos normes de qualité.

Dans la solution proposée ici, j'utilise une bibliothèque Python pre-commit pour exécuter automatiquement tous les outils de vérification avant chaque commit. Enfin, je configure une action GitHub pour exécuter les crochets pre-commit avant de fusionner une pull request dans la branche principale afin d'appliquer finalement la qualité du code.

Problème 3: Packaging

Problème

Super, vous avez un projet prêt à être empaqueté et publié sur pipy ! Mais attendez, vous devez d'abord le préparer pour la publication et passer par une liste d'étapes qui peuvent être fastidieuses (voir ici).

Solution

Encore une fois, Poetry nous aide dans ce cas. Il est super simple de construire et publier votre package. Vous avez principalement 2 commandes à utiliser : poetry build et poetry publish. N'ayez jamais peur de publier votre package.

Bonus : Intégration VSCode

Si vous utilisez VSCode, il existe un excellent langage serveur Python appelé Pylance. Il vérifiera statiquement votre code pendant que vous tapez, améliorera la clarté du code avec une coloration améliorée. Je vous encourage à activer cette fonctionnalité pour tous vos projets. Vous pouvez contrôler le niveau de gravité de la vérification des types, afin de l'adopter progressivement. Il détectera des tonnes d'erreurs potentielles dans votre code simplement en vérifiant les types.

De plus, pour tous les outils mentionnés précédemment, Mypy, Black, Isort et Flake8, il existe des plugins disponibles sur le marché de VSCode.

Enfin, pour intégrer Poetry et VSCode en toute transparence, vous devez indiquer à VSCode l'emplacement de votre interpréteur Python. Comme Poetry le gère pour vous, exécutez poetry run which python pour obtenir le chemin absolu. Ensuite, dans VSCode, appuyez sur Ctrl+P, tapez "Select Python interpreter", puis entrez le chemin.

Le meilleur modèle Python pour commencer

Mettre en pratique toutes ces bonnes pratiques peut sembler trop exigeant, surtout si vous êtes débutant. Cependant, je vous encourage à appliquer ces bonnes pratiques dès que possible dans vos habitudes de codage. Cela vous rendra globalement meilleur développeur, produira du code de meilleure qualité et évitera des pièges et des bugs faciles à repérer. Même pour un programmeur avancé, il peut être fastidieux de le faire encore et encore pour chaque projet.

Mettre en place ces outils n'est pas la partie la plus excitante, mais c'est une étape nécessaire vers le succès.

J'ai donc facilité votre vie ! J'ai créé un [référentiel de modèle GitHub][github repo] qui résout tous ces problèmes. Il est facile à utiliser, lorsque vous créez un nouveau projet Python, démarrez-le à partir de mon modèle GitHub. Vous n'aurez qu'à exécuter poetry install pour obtenir toutes les dépendances de développement requises pour les outils : linting, formatting, vérification des types. Vous aurez également poetry pour gérer vos dépendances et être prêt à livrer du code de haute qualité en un rien de temps ! Jetez-y un coup d'œil.

Comment créer un nouveau référentiel à partir du modèle Comment créer un nouveau référentiel à partir du modèle




Modèle parfait pour démarrer des projets Python

Modèle parfait pour démarrer des projets Python

Python est un excellent langage avec de nombreuses bibliothèques disponibles. Du jeu à l'intelligence artificielle, en passant par le back-end ou l'automatisation. Il y a toutefois un inconvénient majeur : le manque de structure et le désordre dû aux types dynamiques. Dans cet article, j'identifie tous ces problèmes et je vous propose une solution pour chacun d'entre eux. Enfin, je partage avec vous un référentiel de modèle GitHub pour démarrer vos nouveaux projets Python du bon pied et livrer du code de haute qualité en un rien de temps !

Consultez le référentiel sur : Check the GitHub repository. Laissez une étoile si le dépôt vous aide !

Introduction

En tant qu'ingénieur en apprentissage automatique, Python est l'un des outils que j'utilise au quotidien. C'est un langage expressif, rapide à écrire et il bénéficie de l'un des écosystèmes les plus riches, sans oublier que la plupart des outils pour construire de l'intelligence artificielle sont disponibles en Python. Cependant, j'identifie deux principaux inconvénients qui peuvent nuire à votre productivité et à la robustesse de votre code : le manque de structure (types dynamiques) et le manque d'outils de qualité de code intégrés.

Problème 1: Gestion des dépendances

Problème

L'installation de bibliothèques tierces est une étape essentielle dans tout projet de programmation. Mais ce n'est pas suffisant. Il devrait être possible de contrôler les versions des bibliothèques que vous utilisez et d'installer le projet avec toutes ses dépendances sur n'importe quel ordinateur. Vous souhaitez également une isolation pour éviter de mélanger les dépendances entre différents projets. En effet, si vous avez différents projets dépendant de la même bibliothèque mais avec une version différente, vous ne voulez pas qu'ils entrent en conflit les uns avec les autres.

La manière standard de résoudre ces problèmes en Python est d'utiliser Pypi (pour installer des packages) et les environnements virtuels (pour l'isolation). Le flux de travail typique est le suivant :

  1. Vous créez un dossier pour votre projet
  2. Vous créez un environnement virtuel
  3. Vous installez les dépendances avec pip
  4. Vous stockez la liste des dépendances dans un fichier requirements.txt en utilisant pip freeze

Cela vous offre :

  • Isolation : les packages installés dans l'environnement virtuel sont isolés du reste du système
  • Reproductibilité (dans une certaine mesure) : vous pouvez réinstaller toutes les dépendances lorsque vous téléchargez le projet, mais vous n'êtes pas assuré d'atteindre le même état à un autre moment

Il reste 2 problèmes :

  • Mélange de dépendances : vous obtenez un fichier requirements.txt mélangé avec vos dépendances ainsi que les packages requis par ces dépendances. Il est difficile de suivre facilement les packages dont vous dépendez réellement
  • Faible reproductibilité : vous n'êtes pas assuré d'atteindre le même état des dépendances du projet si vous réinstallez votre projet ultérieurement car pip freeze ne verrouille pas les dépendances.

Solution

Utilisez un autre gestionnaire de packages : Poetry. C'est un gestionnaire de packages et de construction moderne. Il est vraiment simple à utiliser, il vous suffit de fournir un fichier : le fichier pyproject.toml. Il résout les 2 problèmes mentionnés ci-dessus.

  • Dépendances propres : dans votre fichier pyproject.toml, vous ne spécifiez que la dépendance directe de votre projet. Elle ne sera jamais mélangée avec les dépendances d'autres packages
  • Reproductibilité forte : poetry introduit un fichier de verrouillage poetry.lock dans votre projet. Dans ce fichier, toutes les dépendances sont verrouillées à la version résolue lors de l'installation. Vous êtes assuré d'avoir le même état des dépendances pour votre projet chaque fois que vous l'installez

Problème 2: Qualité du code et CI/CD

Problème

Super, nous avons résolu le problème de gestion des dépendances ! Mais qu'en est-il de l'application de la qualité du code dans votre projet ? Avec un langage à typage statique comme Rust ou Java, le compilateur détecte de nombreux problèmes lors de la compilation. Malheureusement, nous n'avons pas cette chance avec notre cher langage à typage dynamique.

Un autre facteur important dans une bonne base de code est la cohérence. Python ne dispose pas d'un formateur de code par défaut, mais nous devons d'une certaine manière imposer de bonnes pratiques de mise en forme et idéalement, nous voulons que cela soit automatique.

Solution

Une bonne solution couvre 5 points.

1. Vérification statique des types

Python a introduit les annotations de type vers la version 3.5. Il existe d'excellents outils construits autour de cette fonctionnalité d'annotation de type. N'oubliez pas que les annotations de type ne sont pas obligatoires en Python, c'est une fonctionnalité facultative. Vous pouvez exécuter votre code même si les annotations sont incorrectes ou non respectées. Pour effectuer la vérification réelle des types et vérifier que notre code est correct au moment de la compilation, nous utiliserons Mypy. C'est un vérificateur de types statiques conçu pour Python. Si vous venez de langages à typage statique, les vérifications du compilateur vous manqueront pour détecter de nombreux bugs potentiels. Mypy vous forcera à passer un peu de temps à écrire et à respecter les annotations de type, mais ce investissement portera ses fruits plus rapidement que vous ne le pensez.

2. Formatage

Pour formater le code Python, mes outils préférés sont Black et Isort. Ils viennent avec un ensemble prédéfini de règles qui sont un excellent choix par défaut et que vous pouvez facilement personnaliser dans la configuration pyproject.toml. Black vous aidera à formater votre code, par exemple, en cassant les lignes trop longues, en imposant des retours à la ligne entre les fonctions, etc. Isort vous aidera à garder vos imports triés avec une séparation entre les dépendances intégrées à Python, les dépendances internes et les dépendances tierces. Il est préférable de le maintenir cohérent dans tous les fichiers de votre projet.

Avant/après le formatage du code Avant/après le formatage du code

3. Linting

Le linting est un autre outil de qualité du code. Il vérifie votre code par rapport à une longue liste de règles et vous indique celles que vous enfreignez. Des règles comme les variables inutilisées, les noms en double, l'héritage incorrect, ... C'est important pour la santé de votre projet. Il existe de nombreux linters disponibles tels que Pylint, Flake8, Autopep ... Personnellement, j'utilise Flake8.

4. Tests

Python dispose d'une prise en charge native des tests unitaires. Cependant, je vous encourage à utiliser Pylint qui est un outil puissant pour écrire des tests avec des fonctionnalités qui vous facilitent la vie, notamment grâce à des fixtures. Je reviendrai peut-être sur Pytest dans un autre article.

5. CI/CD

Il est fort probable que vous utilisiez un outil comme GitHub pour sauvegarder votre dépôt Git à distance. Idéalement, vous souhaitez exécuter tous vos contrôles de qualité du code avant que code soit fusionné dans votre branche principale afin d'éviter la dégradation de la base de code au fil du temps. Nous avons deux façons complémentaires de le faire :

  1. Crochets pre-commit : ce sont des scripts exécutés avant chaque commit en local, ils exécuteront tous vos outils de qualité de code et refuseront le commit si le code ne passe pas. C'est un moyen simple d'appliquer les meilleures pratiques à chaque commit.
  2. GitHub actions : ce sont des scripts exécutés automatiquement par GitHub lors de certains déclencheurs. Par exemple, lorsque vous ouvrez une pull request, GitHub construira votre code dans un conteneur et exécutera tous vos contrôles de code. Il vous empêchera de fusionner la pull request dans la branche principale si les vérifications n'ont pas réussi.

Utiliser une combinaison des deux méthodes est recommandé. En effet, les crochets pre-commit sont rapides car ils s'exécutent localement, vous n'avez pas besoin d'attendre le processus à distance de GitHub. Cependant, rien ne garantit que chaque développeur exécute les crochets pre-commit avant de pousser le code. Ainsi, avoir les GitHub actions qui vérifient votre code est la garantie ultime que tout le code fusionné sur la branche principale répond à vos normes de qualité.

Dans la solution proposée ici, j'utilise une bibliothèque Python pre-commit pour exécuter automatiquement tous les outils de vérification avant chaque commit. Enfin, je configure une action GitHub pour exécuter les crochets pre-commit avant de fusionner une pull request dans la branche principale afin d'appliquer finalement la qualité du code.

Problème 3: Packaging

Problème

Super, vous avez un projet prêt à être empaqueté et publié sur pipy ! Mais attendez, vous devez d'abord le préparer pour la publication et passer par une liste d'étapes qui peuvent être fastidieuses (voir ici).

Solution

Encore une fois, Poetry nous aide dans ce cas. Il est super simple de construire et publier votre package. Vous avez principalement 2 commandes à utiliser : poetry build et poetry publish. N'ayez jamais peur de publier votre package.

Bonus : Intégration VSCode

Si vous utilisez VSCode, il existe un excellent langage serveur Python appelé Pylance. Il vérifiera statiquement votre code pendant que vous tapez, améliorera la clarté du code avec une coloration améliorée. Je vous encourage à activer cette fonctionnalité pour tous vos projets. Vous pouvez contrôler le niveau de gravité de la vérification des types, afin de l'adopter progressivement. Il détectera des tonnes d'erreurs potentielles dans votre code simplement en vérifiant les types.

De plus, pour tous les outils mentionnés précédemment, Mypy, Black, Isort et Flake8, il existe des plugins disponibles sur le marché de VSCode.

Enfin, pour intégrer Poetry et VSCode en toute transparence, vous devez indiquer à VSCode l'emplacement de votre interpréteur Python. Comme Poetry le gère pour vous, exécutez poetry run which python pour obtenir le chemin absolu. Ensuite, dans VSCode, appuyez sur Ctrl+P, tapez "Select Python interpreter", puis entrez le chemin.

Le meilleur modèle Python pour commencer

Mettre en pratique toutes ces bonnes pratiques peut sembler trop exigeant, surtout si vous êtes débutant. Cependant, je vous encourage à appliquer ces bonnes pratiques dès que possible dans vos habitudes de codage. Cela vous rendra globalement meilleur développeur, produira du code de meilleure qualité et évitera des pièges et des bugs faciles à repérer. Même pour un programmeur avancé, il peut être fastidieux de le faire encore et encore pour chaque projet.

Mettre en place ces outils n'est pas la partie la plus excitante, mais c'est une étape nécessaire vers le succès.

J'ai donc facilité votre vie ! J'ai créé un [référentiel de modèle GitHub][github repo] qui résout tous ces problèmes. Il est facile à utiliser, lorsque vous créez un nouveau projet Python, démarrez-le à partir de mon modèle GitHub. Vous n'aurez qu'à exécuter poetry install pour obtenir toutes les dépendances de développement requises pour les outils : linting, formatting, vérification des types. Vous aurez également poetry pour gérer vos dépendances et être prêt à livrer du code de haute qualité en un rien de temps ! Jetez-y un coup d'œil.

Comment créer un nouveau référentiel à partir du modèle Comment créer un nouveau référentiel à partir du modèle