Définition
Diviser un nombre par un autre a presque toujours un résultat, sauf dans un cas précis : diviser par zéro n'a pas de solution en mathématiques, et Python ne peut pas décider à votre place ce que ce résultat devrait être. Plutôt que d'inventer un chiffre, il arrête le calcul net et lève l'exception ZeroDivisionError.
Voici ce que cela donne quand un effectif retombe à zéro :
effectif = 0 # personne n'a encore été inscrit
total_des_notes = 240
moyenne = total_des_notes / effectif
# ZeroDivisionError: division by zeroLe traceback indique la ligne exacte, mais pas l'origine du zéro, et c'est justement cette question qui compte. Une division par zéro est rarement une faute de calcul : c'est une donnée absente, une liste vide ou un compteur resté à zéro, qui a traversé le programme sans se faire remarquer jusque-là.
ZeroDivisionError hérite de ArithmeticError, la classe que Python réserve aux erreurs de calcul. Pour intercepter plusieurs erreurs arithmétiques d'un coup, une division par zéro et un dépassement de capacité par exemple, c'est cette classe parente qu'il faut viser dans le except.
Trois opérateurs, un même refus
La division classique n'est pas la seule à buter sur ce mur : le quotient entier et le reste d'une division refusent exactement de la même façon dès que le diviseur vaut zéro. Seul l'opérateur employé change la phrase affichée à la fin du message.
Le tableau suivant récapitule ce que vous obtenez selon l'opérateur et le type des nombres en jeu :
| Expression | Message obtenu |
|---|---|
7 / 0 | division by zero |
7 // 0 | integer division or modulo by zero |
7 % 0 | integer modulo by zero |
7.0 / 0 | float division by zero |
0 / 0 | La même erreur, un dividende nul ne sauve rien |
Ce message mérite d'être lu, car il précise si le calcul portait sur un int ou sur un float, ce qui aide souvent à retrouver la variable fautive. D'autres langages renvoient un infini silencieux dans ce cas, alors que Python arrête tout : une erreur immédiate se repère bien plus vite qu'un infini qui se propage dans les calculs suivants.
La corriger avant qu'elle ne survienne
Une fois qu'un diviseur peut valoir zéro, deux solutions s'offrent à vous. La première vérifie le diviseur avant de s'en servir, la seconde laisse le calcul se dérouler et rattrape l'échec avec try et except.
Voici la première approche :
def moyenne(notes):
if not notes:
return None
return sum(notes) / len(notes)Cette écriture répond à la vraie question posée par une collection vide : une moyenne sans notes n'existe pas, et None le dit honnêtement. Passer par len avant de diviser reste le réflexe le plus lisible dès que le diviseur compte des éléments.
La seconde approche suppose au contraire que zéro est une valeur normale, pas une anomalie.
try:
taux = clics / impressions
except ZeroDivisionError:
taux = 0.0 # aucune impression n'a encore eu lieuLe rattrapage a du sens quand zéro est prévisible et qu'un repli est raisonnable, un taux de clic nul par exemple. Il en a moins quand ce zéro signale une donnée manquante : écraser l'erreur sous un 0.0 fabrique un chiffre faux, qui ira jusqu'au tableau de bord sans que personne ne s'en aperçoive.
Écrire except: sans préciser ZeroDivisionError attrape aussi des erreurs qui n'ont rien à voir, une faute de frappe dans un nom de variable par exemple. Le vrai bogue continue d'exister, simplement caché derrière un rattrapage qui ne lui était pas destiné.
Le zéro vient toujours d'ailleurs
Cette erreur se corrige en une seule ligne, ce qui explique qu'elle soit si souvent mal corrigée : ajouter un test ou un rattrapage soigne le symptôme, pas la cause. Le vrai travail consiste à remonter jusqu'à l'endroit où ce zéro est apparu.
Les sources habituelles ne sont pas nombreuses : une liste vidée par un filtre trop strict, un compteur jamais incrémenté, une saisie convertie sans garde-fou, ou une colonne absente d'un fichier importé. Le calcul n'est pas le coupable, il n'est que le messager.
Une règle simple évite de longues recherches : quand un diviseur ne devrait jamais valoir zéro, mieux vaut le dire franchement avec raise et un message explicite, plutôt que de laisser le calcul échouer plus loin. L'erreur se produit alors au bon endroit, avec le bon nom de variable, et non trois fonctions plus tard.
Questions fréquentes
Pourquoi Python refuse-t-il de renvoyer l'infini ?
Parce qu'aucune valeur ne satisfait réellement la définition d'un quotient par zéro, et qu'un infini silencieux se propagerait ensuite dans tous les calculs qui en dépendent. Le module math et les bibliothèques de calcul scientifique proposent ce comportement quand il est vraiment recherché, mais ce n'est jamais le choix par défaut.
Faut-il tester le diviseur ou rattraper l'erreur ?
Testez quand le zéro est prévisible et fréquent, une collection vide par exemple. Rattrapez quand il reste exceptionnel et imprévu. Un test posé juste avant la division se relit en général mieux qu'un bloc de rattrapage, et il évite au passage d'attraper une erreur venue d'ailleurs dans le code.
Un nombre décimal très petit provoque-t-il la même erreur ?
Non, diviser par 0.000001 fonctionne très bien et renvoie un résultat énorme mais parfaitement valide. Seul un zéro exact déclenche le refus, ce qui rend certains calculs sur les décimaux trompeurs : une valeur ramenée à zéro par un round mal placé redevient, elle, un diviseur interdit.