Python 2 vs Python 3 : Guide Complet des Differences et Migration

Guide complet sur les differences entre Python 2 et Python 3, strategies de migration avec 2to3, bonnes pratiques, pieges courants et implementations alternatives comme IronPython et Jython.

Mahmoud DEVO
Mahmoud DEVO
December 27, 2025 7 min read
Python 2 vs Python 3 : Guide Complet des Differences et Migration

Introduction

Si vous etes developpeur Python, vous avez probablement deja rencontre certaines difficultes lors de la migration de votre code de Python 2.x a Python 3.x. Les differences entre les deux versions peuvent etre importantes et necessitent une comprehension approfondie des nouvelles fonctionnalites et syntaxes introduites dans Python 3.x.

Python 2 a officiellement atteint sa fin de vie le 1er janvier 2020, ce qui signifie qu’il ne recoit plus de mises a jour de securite ni de corrections de bugs. Cette realite rend la migration vers Python 3 non seulement souhaitable, mais essentielle pour tout projet professionnel.

Dans cet article, nous allons vous guider a travers les etapes cles pour reussir la migration de votre code. Nous couvrirons les differences fondamentales, les outils de migration automatique, les pieges courants a eviter, et les meilleures pratiques pour ecrire du code compatible.

Pourquoi migrer vers Python 3 ?

  • Securite : Python 2 ne recoit plus de correctifs de securite
  • Performance : Python 3 offre des ameliorations significatives de performance
  • Fonctionnalites modernes : Async/await, type hints, f-strings, etc.
  • Ecosysteme : La plupart des bibliotheques majeures ont abandonne le support Python 2
  • Support communautaire : La communaute Python se concentre sur Python 3

Differences Fondamentales entre Python 2 et Python 3

L’une des differences les plus visibles est le passage de print d’une declaration a une fonction.

# Python 2
print "Hello, World!"
print "Valeur:", 42

# Python 3
print("Hello, World!")
print("Valeur:", 42)

Cette modification permet une plus grande flexibilite avec les arguments nommes :

# Python 3 - Options avancees
print("Hello", end=" ")  # Pas de saut de ligne
print("World", file=sys.stderr)  # Redirection vers stderr
print("a", "b", "c", sep="-")  # Separateur personnalise -> "a-b-c"

Division Entiere vs Flottante

# Python 2
print 5 / 2    # Resultat: 2 (division entiere)
print 5 // 2   # Resultat: 2

# Python 3
print(5 / 2)   # Resultat: 2.5 (division flottante)
print(5 // 2)  # Resultat: 2 (division entiere explicite)

Gestion des Chaines de Caracteres (Unicode)

# Python 2
type("hello")      # <type 'str'> (bytes)
type(u"hello")     # <type 'unicode'>

# Python 3
type("hello")      # <class 'str'> (unicode par defaut)
type(b"hello")     # <class 'bytes'>

Mise en place de classes avec des valeurs booleennes

L’une des differences majeures entre Python 2.x et Python 3.x est la facon dont sont gerees les valeurs booleennes dans les classes. Dans Python 2.x, vous deviez implementer la methode __nonzero__ pour definir une valeur booleenne pour votre classe.

# Python 2
class MyClass:
    def __init__(self, value):
        self.value = value

    def __nonzero__(self):
        return bool(self.value)

my_instance = MyClass(0)
print bool(MyClass)      # True (la classe elle-meme)
print bool(my_instance)  # False (l'instance avec value=0)

Dans Python 3.x, la methode __bool__ est utilisee a la place de __nonzero__.

# Python 3
class MyClass:
    def __init__(self, value):
        self.value = value

    def __bool__(self):
        return bool(self.value)

my_instance = MyClass(0)
print(bool(MyClass))      # True
print(bool(my_instance))  # False

Pour ecrire du code compatible avec les deux versions :

# Code compatible Python 2 et 3
class MyClass:
    def __init__(self, value):
        self.value = value

    def __bool__(self):
        return bool(self.value)

    __nonzero__ = __bool__  # Alias pour Python 2

Range vs xrange

# Python 2
range(5)     # Retourne une liste [0, 1, 2, 3, 4]
xrange(5)    # Retourne un iterateur (plus efficace en memoire)

# Python 3
range(5)     # Retourne un objet range (comme xrange en Python 2)
# xrange n'existe plus

Gestion des Exceptions

# Python 2
try:
    raise ValueError, "Une erreur"
except ValueError, e:
    print e

# Python 3
try:
    raise ValueError("Une erreur")
except ValueError as e:
    print(e)

Outils de Migration

Utilisation du module 2to3

Le module 2to3 est un outil puissant pour convertir votre code de Python 2.x en Python 3.x. Il analyse votre code source et applique automatiquement une serie de transformations.

Analyse sans modification

# Voir les changements proposes sans modifier le fichier
$ 2to3 example.py

# Analyser un dossier entier
$ 2to3 mon_projet/

Ce qui vous donnera les differences entre le fichier d’origine et le fichier refactorise :

RefactoringTool: Refactored example.py
--- example.py (original)
+++ example.py (refactored)
@@ -1,5 +1,5 @@
-print "Hello World"
+print("Hello World")

Application des modifications

# Ecrire les modifications dans le fichier source
$ 2to3 -w example.py

# Convertir un dossier entier avec backup
$ 2to3 -w -n mon_projet/

# Appliquer uniquement certains fixers
$ 2to3 -f print -f except example.py

Bibliotheque six pour la compatibilite

La bibliotheque six permet d’ecrire du code compatible Python 2 et 3 :

import six

# Verification de version
if six.PY2:
    print("Python 2")
else:
    print("Python 3")

# Iterateurs compatibles
for key, value in six.iteritems(mon_dict):
    print(key, value)

# Chaines de caracteres
if isinstance(valeur, six.string_types):
    print("C'est une chaine")

Bibliotheque future

from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from __future__ import unicode_literals

# Maintenant le code se comporte comme Python 3
print("Hello")  # Fonctionne en Python 2 et 3
print(5 / 2)    # Retourne 2.5 en Python 2 et 3

Implementations Alternatives de Python

Il existe plusieurs implementations alternatives de Python qui peuvent etre utiles dans certains contextes specifiques.

IronPython (.NET)

IronPython est une implementation open-source pour .NET et Mono ecrite en C#. Elle repose sur la Dynamic Language Runtime (DLR) et permet une integration etroite avec le framework .NET.

# Exemple IronPython - Acces aux bibliotheques .NET
import clr
clr.AddReference("System.Windows.Forms")

from System.Windows.Forms import MessageBox, Application
from System import Console

Console.WriteLine("Hello depuis IronPython!")
MessageBox.Show("Bonjour!", "Message .NET")

Note : IronPython 2 supporte Python 2.7. IronPython 3 (en developpement) vise la compatibilite Python 3.

Jython (JVM)

Jython est une implementation open-source pour la plateforme JVM ecrite en Java. Elle permet d’utiliser les bibliotheques Java directement depuis Python.

# Exemple Jython - Acces aux bibliotheques Java
from java.lang import System
from java.util import ArrayList, HashMap

System.out.println("Hello depuis Jython!")

# Utilisation de collections Java
liste = ArrayList()
liste.add("Python")
liste.add("Java")

for item in liste:
    print(item)

Note : Jython supporte actuellement Python 2.7 uniquement.

Transcrypt (JavaScript)

Transcrypt est un compilateur qui transforme le code Python en JavaScript compact et lisible. Il prend en charge la programmation orientee objet avec heritage multiple.

# Ce code Python sera compile en JavaScript
from browser import document, alert

def on_click(event):
    alert("Bouton clique!")

document['mon-bouton'].addEventListener('click', on_click)
print("Hello depuis le navigateur!")

PyPy (Performance)

PyPy est une implementation alternative de Python focalisee sur la performance grace a la compilation JIT (Just-In-Time).

# Installation et utilisation de PyPy
$ pypy3 mon_script.py

# Peut etre 4 a 10 fois plus rapide que CPython
# pour certains types de code

Bonnes Pratiques

1. Ecrire du code compatible Python 2/3

Si vous devez maintenir la compatibilite avec Python 2 pendant la transition :

# En-tete recommande pour compatibilite
from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals
)

import sys
PY2 = sys.version_info[0] == 2

# Fonction compatible pour input
if PY2:
    input = raw_input

2. Utiliser des type hints (Python 3.5+)

from typing import List, Dict, Optional

def traiter_utilisateurs(
    utilisateurs: List[Dict[str, str]],
    limite: Optional[int] = None
) -> List[str]:
    """Retourne les noms des utilisateurs."""
    noms = [u['nom'] for u in utilisateurs]
    if limite:
        return noms[:limite]
    return noms

3. Privilegier les f-strings (Python 3.6+)

# Python 3.6+ - f-strings (recommande)
nom = "Alice"
age = 30
print(f"Bonjour {nom}, vous avez {age} ans")

# Equivalent ancien (moins lisible)
print("Bonjour {}, vous avez {} ans".format(nom, age))
print("Bonjour %s, vous avez %d ans" % (nom, age))

4. Utiliser pathlib pour les chemins

from pathlib import Path

# Python 3 - pathlib (recommande)
chemin = Path("/home/user/documents")
fichier = chemin / "rapport.txt"

if fichier.exists():
    contenu = fichier.read_text(encoding='utf-8')
    fichier.write_text("Nouveau contenu")

5. Context managers pour les ressources

# Toujours utiliser with pour les fichiers
with open("fichier.txt", "r", encoding="utf-8") as f:
    contenu = f.read()

# Pour les connexions base de donnees
with sqlite3.connect("db.sqlite") as conn:
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users")

Pieges Courants

1. Encodage des chaines

# PIEGE: Melanger bytes et str
data = b"Hello"
text = "World"

# Erreur en Python 3
# result = data + text  # TypeError!

# Solution: Decoder/encoder explicitement
result = data.decode('utf-8') + text
# ou
result = data + text.encode('utf-8')

2. Division entiere inattendue

# PIEGE: Comportement different de la division
# Python 2: 5/2 = 2
# Python 3: 5/2 = 2.5

# Solution: Etre explicite
quotient = 5 // 2  # Division entiere: 2
resultat = 5 / 2   # Division flottante: 2.5

3. Dictionnaires non ordonnes (Python < 3.7)

# PIEGE: Avant Python 3.7, les dict n'etaient pas ordonnes
# Solution: Utiliser OrderedDict si l'ordre est important
from collections import OrderedDict

config = OrderedDict([
    ('host', 'localhost'),
    ('port', 8080),
    ('debug', True)
])

4. Iterateurs epuises

# PIEGE: Les iterateurs ne peuvent etre parcourus qu'une fois
nombres = map(lambda x: x * 2, [1, 2, 3])
print(list(nombres))  # [2, 4, 6]
print(list(nombres))  # [] - iterateur epuise!

# Solution: Convertir en liste si reutilisation necessaire
nombres = list(map(lambda x: x * 2, [1, 2, 3]))

5. Comparaison de types differents

# Python 2: "1" < 2 ne genere pas d'erreur
# Python 3: TypeError - impossible de comparer str et int

# Solution: Toujours comparer des types compatibles
valeur = "42"
if int(valeur) < 100:
    print("Inferieur a 100")

Conclusion

La migration de Python 2 vers Python 3 est une etape essentielle pour tout projet Python moderne. Voici les points cles a retenir :

  1. Python 2 est obsolete : Plus de support depuis janvier 2020
  2. Utilisez les outils : 2to3, six, et future facilitent la transition
  3. Testez abondamment : Les differences subtiles peuvent causer des bugs
  4. Adoptez les nouvelles fonctionnalites : f-strings, type hints, async/await
  5. Choisissez la bonne implementation : CPython pour la plupart des cas, PyPy pour la performance

Checklist de Migration

  • Analyser le code avec 2to3 (mode preview)
  • Ajouter les imports __future__ pour compatibilite
  • Mettre a jour les dependances vers des versions compatibles Python 3
  • Corriger les problemes d’encodage (unicode/bytes)
  • Adapter la syntaxe print et except
  • Remplacer les iterateurs (xrange, dict.keys(), etc.)
  • Executer les tests unitaires
  • Deployer progressivement

Ressources Supplementaires

La migration peut sembler intimidante, mais avec une approche methodique et les bons outils, elle est tout a fait realisable. Commencez par les modules les plus simples et progressez vers les parties plus complexes de votre code.

Advertisement

In-Article Ad

Dev Mode

Share this article

Mahmoud DEVO

Mahmoud DEVO

Senior Full-Stack Developer

I'm a passionate full-stack developer with 10+ years of experience building scalable web applications. I write about Vue.js, Node.js, PostgreSQL, and modern DevOps practices.

Enjoyed this article?

Subscribe to get more tech content delivered to your inbox.

Related Articles