L’utilisation de l’analyse de code statique ainsi que le formatage du code permet entre autre de
- Définir un cadre de développement.
- S’assurer que les autres développeurs potentiels comprennent ce cadre facilement.
- Conserver une uniformité dans le code.
Concernant le formatage de code, on peut citer deux outils
Chacun d’eux va vous permettre de définir la structure visuelle que vous souhaitez que votre code ait tout en essayant de respecter la PEP 8. Celle-ci définit les règles de nommages, les règles d’espaces, les règles d’indentation, ...
Concernant l’analyse statique, celle-ci est très utile car elle permet de voir certains disfonctionnements avant même d’avoir exécuter du code Python. L’analyse statique peut par exemple vérifier
- les variables non utilisées,
- les paramètres de fonctions non utilisés,
- les comportements étranges
- ...
Là encore, on peut citer deux outils
pylint a été longtemps le meilleur outil car il était beaucoup plus complet que les autres dans les diagnostics et il est facilement configurable.
ruff est jeune mais il offre une rapidité d’exécution incomparable par rapport aux autres outils. Il est écrit en Rust. Même si ruff voit déjà beaucoup de choses, il n’a pas tous les diagnostics de pylint mais c’est en cours (astral-sh/ruff#970).
Dans la suite, nous allons regarder le comportement de ces deux outils sur des bouts de code afin de voir les différences.
Exemples¶
%%file examples/linter/pep8.py
class maCLasse:
def __init__(a, b = 4):
self.a = 5
def fonctionADD(a, b,c):
return a+b
! pylint examples/linter/pep8.py
! ruff check --select ALL examples/linter/pep8.py
%%file examples/linter/missing.py
def process_stuff(params):
executed = False
if not params:
raise ValueError('empty command list')
for foo in params:
foo.execute
! pylint examples/linter/missing.py
! ruff check --select ALL examples/linter/missing.py
%%file examples/linter/numpy_check.py
import numpy as np
a = np.zeros((10, 10), dtype=np.int322)
np.sum(a, axes=0)
! pylint examples/linter/numpy_check.py
! ruff check --select ALL examples/linter/numpy_check.py
%%file examples/linter/similarities/module1.py
def function1(array):
for i in range(10):
for j in range(10):
if (i+j) & 1:
array[i][j] = 1
else:
array[i][j] = 0
%%file examples/linter/similarities/module2.py
def function2(array):
print(array[0])
for i in range(10):
for j in range(10):
if (i+j) & 1:
array[i][j] = 1
else:
array[i][j] = 0
! pylint examples/linter/similarities
! ruff check --select ALL examples/linter/similarities
Avantages de pylint¶
%%file examples/linter/numpy_doc.py
def awesome_function(tomatoes, banana):
"""
This is an awesome function !!
Parameters
----------
tomatoes:
red fruit
apple : int
number of apple
"""
print(tomatoes)
print(banana)
return tomatoes[0]
! pylint --load-plugins=pylint.extensions.docparams examples/linter/numpy_doc.py
%%file examples/linter/spellcheck.py
def some_function():
"""
This fonction does nothing.
But it's a example of spell checking
using pylint.
Don't look at the grammar and work only
for doc strings and comments.
"""
pass
! pylint --spelling-dict en_US examples/linter/spellcheck.py
Annuler certaines vérifications¶
%%file examples/linter/disable.py
# pylint: disable=invalid-name
def function1():
for a in range(10):
print(a)
! pylint examples/linter/disable.py
Fichier de configuration de pylint¶
- Si vous souhaitez qu’il soit utilisé dès que l’on appelle pylint
! pylint --generate-rcfile > ~/.pylintrc
- Si vous souhaitez qu’il soit utilisé uniquement pour un module ou un paquet précis
! pylint --generate-rcfile > pylintrc
! pylint ...
Que contient ce fichier ?¶
- La possibilité de configurer tout ce qu’on a vu avant.
- Une gestion plus fine (par exemple les expressions régulières satisfaisant la PEP 8).
- Le formatage des messages de sortie et le calcul du score.
- La possibiité d’exécuter pylint en multi-threads.
- ...
Exercices¶
Le répertoire step0
reprend la dernière étape du TP précédent.
Références¶
12 years of Pylint - Claudio Paupa
don’t use this code - Mark Shannon