Aller au contenu principal

Python - Les outils de qualité de code

Améliorez la qualité de votre code Python ! Découvrez 9 outils d'analyse statique essentiels comme Pylint, Black et mypy, ainsi qu'un workflow QA optimal pour un code plus propre et sans bugs.

· 10 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
Cet article existe aussi en anglais — lire la version originale.

Traduction automatique

Cette traduction a été produite par une IA. Elle peut contenir des contresens ou des maladresses, en particulier sur les termes techniques. En cas de doute, consultez l'article de référence en anglais — c'est lui qui fait foi.

Journal des modifications

Dernière
Restructured for time-to-value: the make qa run now opens the article, before the tool-by-tool catalog.
pydocstyle GitHub repo was archived November 2023 and is no longer maintained; Ruff (see Extra section) is the recommended replacement for docstring checks.

Python - Les outils de qualité de code

⚡
TL;DR

Cet article recense la chaîne d'outils de qualité de code Python de l'auteur — Pylint, Autoflake, isort, Vulture, pydocstyle, mypy, Pyright, Black et Prospector, plus Ruff comme alternative tout-en-un ultra rapide — avec, pour chacun, la commande CLI exacte et le fichier de configuration. Ils sont enchaînés, du plus rapide/plus fondamental en premier, dans une cible make qa qui s'arrête au premier échec et n'affiche « CONGRATULATIONS » que si toutes les vérifications passent.

Si vous êtes un programmeur qui se respecte, vous ne pouvez pas développer sans outils d'analyse de code. Pour les programmeurs PHP, vous en connaissez déjà beaucoup (rector, phpstan, phan, phpcs, ...). Voyez mes articles précédents Rector 1.0.0, my friend, my coach et Une image Docker qui fournit les outils d'analyse statique pour PHP.

Et pour Python ?

Le résultat : une commande, neuf vérifications, un seul point d'échec​

make qa enchaîne Pylint, Autoflake, isort, Vulture, pydocstyle, mypy, Pyright, Black et Prospector — l'outil le plus rapide d'abord — et s'arrête au tout premier échec. Voici à quoi ressemble une exécution propre :

>user@machine: ~/yourproject

Rien de vert à chercher : le silence (ou une note comme le 10.00/10 de Pylint) signifie que la vérification est passée. Il en rate une seule et la chaîne s'arrête là — pas de CONGRATULATIONS, et une seule chose à corriger avant de relancer.

Pourquoi ça fonctionne​

  • Les outils s'exécutent du plus rapide/plus fondamental en premier : inutile de lancer un vérificateur de types lent si le code ne se parse même pas — c'est pourquoi Pylint est 1/9 et Autoflake, qui nettoie les imports, est 2/9.
  • La chaîne s'arrête au premier échec : une exécution de make qa, une chose claire à corriger, pas neuf rapports à recouper.
  • make qa est un point d'entrée unique : c'est la même cible que vous lancez à la main, que lance un hook pre-commit et que lance la CI — j'y reviens en conclusion.

Mise en place​

Je suis un grand fan des outils statiques de qualité de code, et voici ma courte liste, câblée ensemble avec une action makefile appelée qa :

# cspell:disable
.PHONY: qa
qa:
@printf "\e[1;37m%-35s%-10s%-10s\e[m%s\n" " Step Tool" "Run?" "Techno" "Description"
@echo "--------------------------------------------------------------------------------------------------------------"
@printf "\e[1;37m%-35s%-10s%-10s\e[m%s\n" " 1/9 RUNNING make Pylint" "Lint python scripts using Pylint (https://pypi.org/project/pylint/)"
@pylint . --rcfile .config/.pylintrc
@printf "\e[1;37m%-35s%-10s%-10s\e[m%s\n" " 2/9 RUNNING make Autoflake" "Detect unused variables and unused imports (https://pypi.org/project/autoflake/)"
@autoflake --remove-unused-variables --remove-all-unused-import --recursive .
@printf "\e[1;37m%-35s%-10s%-10s\e[m%s\n" " 3/9 RUNNING make isort" "Sort import statement using isort (https://pycqa.github.io/isort/)"
@isort .
@printf "\e[1;37m%-35s%-10s%-10s\e[m%s\n" " 4/9 RUNNING make Vulture" "Find dead Python code (https://github.com/jendrikseipp/vulture)"
@vulture --min-confidence 100 .
@printf "\e[1;37m%-35s%-10s%-10s\e[m%s\n" " 5/9 RUNNING make Pydocstyle" "pydocstyle is a static analysis tool for checking compliance with Python docstring conventions (https://www.pydocstyle.org/en/stable/)"
@pydocstyle --config=.config/.pydocstyle
@printf "\e[1;37m%-35s%-10s%-10s\e[m%s\n" " 6/9 RUNNING make Mypy" "Mypy is a program that will type check your Python code (https://github.com/python/mypy/)"
@mypy --config-file .config/.mypy.ini .
@printf "\e[1;37m%-35s%-10s%-10s\e[m%s\n" " 7/9 RUNNING make Pyright" "Pyright is a full-featured, standards-based static type checker for Python (https://github.com/microsoft/pyright)"
@pyright --project .config/pyright.json
@printf "\e[1;37m%-35s%-10s%-10s\e[m%s\n" " 8/9 RUNNING make Black" "Format the script using Black (https://black.readthedocs.io/en/stable/)"
@black --config .config/black.toml .
@printf "\e[1;37m%-35s%-10s%-10s\e[m%s\n\n" " 9/9 RUNNING make Prospector" "Inspects Python source files and provides information about type and location of classes, methods, ... (https://github.com/prospector-dev/prospector/)"
@prospector . --profile .config/prospector.yaml --pylint-config-file .config/.pylintrc
@printf "%s\n" "CONGRATULATIONS!!!"
@printf "%s\n" "Not the slightest error or notice detected, that's .. amazing!"
@printf "%s\n" "🥳 🎉 🎊 🤩 🕺 💃 👏"

Cette cible Makefile qa exécute une suite complète de neuf outils de vérification et de formatage de code Python. Elle lance successivement pylint, autoflake, isort, vulture, pydocstyle, mypy, pyright, black et prospector, en affichant une description formatée de chaque étape. À la fin, si tout s'est bien déroulé sans erreurs, elle affiche un message de félicitations.

Dès qu'une erreur est détectée, le script s'arrête. Vous ne verrez le message CONGRATULATIONS, exactement comme montré ci-dessus, que si les neuf vérifications réussissent.

Plus de démos : les neuf outils, un par un​

1. Pylint, l'analyseur statique​

https://pypi.org/project/pylint/

Extension VSCode

Pylint est un analyseur de code statique pour Python 2 ou 3. La dernière version supporte Python 3.9.0 et supérieur.

Pylint analyse votre code sans réellement l'exécuter. Il cherche les erreurs, applique un standard de codage, repère les code smells et peut suggérer comment le code pourrait être refactorisé.

Commençons par le commencement : assurez-vous que votre code Python n'a pas d'erreurs de syntaxe — pas de mauvaise indentation, pas de : oublié à la fin d'une instruction de contrôle (comme un if ou un for).

Je le lance comme ceci : pylint . --rcfile .config/.pylintrc.

[MASTER]
; Pickle collected data for later comparisons.
persistent=yes
; List of plugins (as comma-separated values of python modules names) to load,
; usually to register additional checkers.
load-plugins=
pylint.extensions.check_elif,
pylint.extensions.bad_builtin,
pylint.extensions.docparams,
pylint.extensions.for_any_all,
pylint.extensions.set_membership,
pylint.extensions.code_style,
pylint.extensions.overlapping_exceptions,
pylint.extensions.typing,
pylint.extensions.redefined_variable_type,
pylint.extensions.comparison_placement,
; Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
; number of processors available to use.
jobs=0
; When enabled, pylint would attempt to guess common misconfiguration and emit
; user-friendly hints instead of false-positive error messages.
suggestion-mode=yes
; Minimum supported python version
py-version = 3.13.0
; Specify a score threshold to be exceeded before program exits with error.
fail-under=9.50
[FORMAT]
max-line-length=120

Ce fichier configure pylint, un outil qui vérifie la qualité du code Python. Il active la sauvegarde des résultats pour des comparaisons futures, charge plusieurs extensions de vérification, utilise tous les processeurs disponibles pour accélérer l'analyse, et définit des seuils de qualité minimale pour le projet.

2. Autoflake, le nettoyage des imports inutilisés​

https://pypi.org/project/autoflake/

Autoflake supprime les imports et les variables inutilisés du code Python. Il s'appuie sur pyflakes pour cela.

Par défaut, Autoflake ne supprime que les imports inutilisés des modules faisant partie de la bibliothèque standard. (D'autres modules peuvent avoir des effets de bord rendant leur suppression automatique risquée.) La suppression des variables inutilisées est également désactivée par défaut.

Autoflake supprime aussi par défaut les instructions pass inutiles.

Je le lance comme ceci : autoflake --remove-unused-variables --remove-all-unused-import --recursive .

3. isort, le tri des imports​

https://pycqa.github.io/isort/

Extension VSCode

isort trie vos imports, pour que vous n'ayez pas à le faire.

isort est un utilitaire / une bibliothèque Python qui trie les imports par ordre alphabétique et les sépare automatiquement en sections et par type. Il fournit un utilitaire en ligne de commande, une bibliothèque Python et des plugins pour divers éditeurs afin de trier rapidement tous vos imports. Il nécessite Python 3.7+ pour fonctionner mais sait aussi formater du code Python 2.

Je le lance comme ceci : isort .

Note : j'ai aussi configuré mon VSCode avec ce réglage "python.sortImports.args": ["--profile", "black"] pour que les instructions d'import soient triées automatiquement pendant que je code.

4. vulture, la détection de code mort​

https://github.com/jendrikseipp/vulture

Vulture trouve le code inutilisé dans les programmes Python. C'est utile pour nettoyer et trouver des erreurs dans de grandes bases de code. Si vous lancez Vulture à la fois sur votre bibliothèque et sur votre suite de tests, vous pouvez repérer le code non testé.

À cause de la nature dynamique de Python, les analyseurs statiques comme Vulture risquent de manquer du code mort. Par ailleurs, du code appelé uniquement de manière implicite peut être signalé comme inutilisé. Malgré tout, Vulture peut être un outil très utile pour une meilleure qualité de code.

Je le lance comme ceci : vulture --min-confidence 100 .

Danger

Attention avec Vulture : son algorithme détecte beaucoup de faux positifs, c'est pourquoi, dans mon processus d'automatisation, j'ai utilisé --min-confidence 100 pour être sûr de n'avoir que du vrai code / de vraies variables inutilisés.

Note : j'ai aussi configuré mon VSCode avec les réglages ci-dessous pour que, pendant que je code, VSCode me signale les éléments inutilisés et que je puisse réagir immédiatement.

"python.analysis.diagnosticSeverityOverrides": {
"reportUnusedClass": "information",
"reportUnusedFunction": "information",
"reportUnusedImport": "information",
"reportUnusedVariable": "information"
},

Ce fichier configure les paramètres d'analyse Python pour Pylance ou un outil d'analyse similaire. Il réduit le niveau de sévérité des diagnostiques relatifs aux éléments inutilisés (classes, fonctions, imports, variables) du niveau d'erreur au niveau d'information, pour que ces avertissements soient moins intrusifs.

5. pydocstyle, la qualité des docstrings​

https://www.pydocstyle.org/en/stable/

pydocstyle est un outil d'analyse statique qui vérifie le respect des conventions de docstrings Python.

Cet outil vérifie la qualité de vos commentaires, comme les descriptions de vos fonctions et, par exemple, s'assure que si vous avez une fonction avec deux arguments, votre description explique les deux arguments (il y a un contrôle sur le nom et sur le type).

Je le lance comme ceci : pydocstyle --config=.config/.pydocstyle

[pydocstyle]
ignore = D100,D203,D205,D212,D213,D400,D404,D406,D407,D413,D415
match = .*\.py

Ce fichier de configuration pydocstyle définit les règles de vérification des docstrings Python. Il exclut plusieurs codes d'erreur spécifiques (comme D100 pour les docstrings de module manquantes) et configure l'outil pour analyser tous les fichiers se terminant par .py.

Attention

Le repository GitHub de pydocstyle a été archivé en novembre 2023 et n'est plus activement maintenu. La communauté recommande de migrer vers Ruff (voir la section « Sous le capot » ci-dessous), qui couvre des vérifications de docstrings équivalentes via son jeu de règles compatible pydocstyle.

6. mypy, le typage statique​

https://github.com/python/mypy/

Mypy est un vérificateur de types statique pour Python.

Les vérificateurs de types aident à s'assurer que vous utilisez correctement les variables et les fonctions de votre code. Avec mypy, ajoutez des annotations de type (PEP 484) à vos programmes Python, et mypy vous avertira quand vous utiliserez ces types de façon incorrecte.

Python est un langage dynamique : d'ordinaire, vous ne voyez les erreurs de votre code qu'au moment de l'exécuter. Mypy est un vérificateur statique, il trouve donc les bugs de vos programmes sans même les exécuter !

Je le lance comme ceci : mypy --config-file .config/.mypy.ini .

[mypy]
show_error_codes = true
; First we turn on *all the checks*, and then we turn off those that are too annoying.
strict = True
cache_dir = /tmp/mypy
no_implicit_optional = true
strict_equality = true
warn_redundant_casts = true
warn_unused_ignores = true
python_version = 3.13

Ce fichier configure mypy, l'outil de vérification de types pour Python, en activant le mode strict pour détecter les erreurs de typage. On active tous les contrôles stricts possibles et on configure quelques paramètres comme la version Python et le répertoire de cache.

7. Pyright, l'autre vérificateur de types​

https://github.com/microsoft/pyright

Pyright est un vérificateur de types statique complet et basé sur les standards pour Python. Il est conçu pour la performance et peut être utilisé sur de grandes bases de code Python.

Je l'utilise comme ceci : pyright --project .config/pyright.json

{
"include": [ "." ],
"pythonVersion": "3.13",
"pythonPlatform": "Linux"
}

Ce fichier de configuration pyrightconfig.json configure l'analyseur statique Pyright pour vérifier le code Python du répertoire courant. Il spécifie que le projet cible Python 3.13 sur une plateforme Linux.

8. Black, le formatage automatique​

https://black.readthedocs.io/en/stable/

Extension VSCode

En utilisant Black, vous acceptez de céder le contrôle sur les détails du formatage manuel. En échange, Black vous donne de la vitesse, du déterminisme et la liberté de ne plus subir les remarques de pycodestyle sur le formatage. Vous économiserez du temps et de l'énergie mentale pour des sujets plus importants.

Black accélère la revue de code en produisant les diffs les plus petits possibles. Le code passé à Black a la même allure quel que soit le projet que vous lisez. Le formatage devient transparent au bout d'un moment et vous pouvez vous concentrer sur le contenu.

Je l'utilise comme ceci : black --config .config/black.toml .

[tool.black]
# The same as in prospector.yaml and .pylintrc
line-length = 120
# We'll format the code for Python 3.13.0; we can add multiple versions (the ones supported by
# the script, all versions separated by a comma like in ['py312', 'py313'] (run "black --help" to get them)
target-version = ['py313']

Ce fichier configure Black, l'outil de formatage de code Python. Il définit une longueur de ligne maximale de 120 caractères et cible Python 3.13 comme version de formatage.

9. prospector, l'inspection globale​

https://github.com/prospector-dev/prospector/

Inspecte les fichiers source Python et fournit des informations sur le type et l'emplacement des classes, méthodes, etc.

Je l'utilise comme ceci : prospector . --profile .config/prospector.yaml --pylint-config-file .config/.pylintrc

strictness: high
test-warnings: true
doc-warnings: false
pycodestyle:
options:
max-line-length: 120
disable:
- D100
- D203
- D205
- D212
- D213
- D400
- D404
- D406
- D407
- D413
- D415
bandit:
run: true
dodgy:
run: true
pyflakes:
run: true
mccabe:
run: true

Ce fichier configure les outils de vérification de qualité de code Python. Il active des vérificateurs comme bandit, dodgy, pyflakes et mccabe, désactive certaines règles de documentation pycodestyle jugées trop strictes, et fixe la longueur maximale des lignes à 120 caractères.

Sous le capot (passez votre chemin si vous voulez juste l'utiliser)​

En bonus - Ruff, un remplaçant potentiel pour plusieurs outils​

https://github.com/astral-sh/ruff

Ruff, un linter et formateur de code Python extrêmement rapide, écrit en Rust.

Extension VSCode

Pour l'instant, j'ai trop peu d'expérience avec Ruff, je préfère donc l'ajouter en bonus.

La documentation indique qu'il est extrêmement rapide et je dois avouer que, la première fois que je l'ai lancé, je pensais que rien ne s'était passé (vraiment trop rapide). J'ai introduit une erreur volontaire dans mon code et elle a été correctement détectée : oui, l'outil est extrêmement rapide.

D'après la documentation de Ruff, cet outil peut remplacer complètement Pylint (le linter), Autoflake (suppression des imports/variables inutilisés) et Black (l'outil de formatage), mais il ne remplace pas MyPy ni Pyright (doc).

Je l'utilise comme ceci : ruff format --cache-dir /tmp/ruff --config .config/pyproject.toml . et ruff check --cache-dir /tmp/ruff --config .config/pyproject.toml .

[tool.ruff]
exclude=[]
# The same as in prospector.yaml, .pylintrc, black.toml and pyproject.toml
line-length = 120
indent-width = 4

Ce fichier configure l'outil Ruff, un linter et formateur Python rapide. Il définit les paramètres de base : aucun fichier n'est exclu de la vérification, la longueur maximale des lignes est de 120 caractères, et l'indentation utilise 4 espaces. Ces paramètres sont synchronisés avec d'autres outils de qualité de code du projet.

Conclusion​

Neuf outils, une commande, un seul point d'échec — make qa transforme le « est-ce que j'ai pensé à tout vérifier ? » en une exécution déterministe unique, la vérification la plus rapide/fondamentale d'abord, qui s'arrête dès que quelque chose cloche.

Le lancer à la main suppose quand même que vous y pensiez. Deux façons de l'automatiser : Git - pre-commit-hooks refuse le commit quand une vérification échoue, et Dagger.io - Utiliser dagger pour automatiser vos workflows CI exécute exactement les mêmes étapes en local et dans votre CI.


🦋 Rejoignez la conversation sur BlueskyUn compte Bluesky gratuit est nécessaire pour aimer, repartager ou commenter. Ce bloc interroge l'API publique de Bluesky directement depuis votre navigateur (sans cookie, sans connexion) — votre adresse IP parvient donc aux serveurs de Bluesky dès que cette section se charge.

Chargement des commentaires…

Cet article vous a-t-il été utile ?
Avez-vous suivi les étapes de cet article ?