En Python, pour la sérialisation (conversion d'objets en séquence d'octets ou chaîne pour le stockage/transmission), on utilise les modules pickle et json:
Utiliser Pickle pour stocker/transmettre des données entre des parties non contrôlées est dangereux, car lors de la désérialisation, on peut exécuter un code malveillant arbitraire. json ne présente pas cet inconvénient.
Exemple de fonctionnement :
import pickle import json # Pickle (sérialisation binaire) data = {'x': 10, 'func': lambda x: x + 1} with open('data.pkl', 'wb') as f: pickle.dump(data, f) # JSON (seulement des objets simples) data = {'x': 10, 'y': [1, 2, 3]} with open('data.json', 'w') as f: json.dump(data, f)
Question : Peut-on utiliser pickle pour sérialiser et sauvegarder n'importe quel objet Python entre les sessions ? Pourquoi ce mécanisme n'est-il pas recommandé pour la sauvegarde des données utilisateurs ?
Réponse :
Non, utiliser pickle partout est une mauvaise pratique. En plus de la sécurité (lors du chargement d'un objet pickle "étranger", l'exécution peut être compromise), il y a le problème de compatibilité des versions de Python ou des classes — les objets sérialisés peuvent ne pas se charger ou se comporter de manière incorrecte si la structure des classes a changé.
Exemple :
# Chargement d'un fichier pickle, la structure de la classe a changé import pickle with open('old_version.pkl', 'rb') as f: obj = pickle.load(f) # AttributeError ou divergence de structure
Histoire
Dans un grand projet, pour le stockage des profils utilisateurs, on a utilisé pickle. Après la mise à jour de la version de Python et les changements de classes, la structure des objets sérialisés a perdu sa compatibilité, ce qui a entraîné l'échec du système et la perte de la plupart des données utilisateurs.
Dans un service web, pickle a été utilisé pour les sessions des utilisateurs. Un malveillant a téléchargé un objet pickle malveillant, permettant l'injection de code sur le serveur.
Une tentative de sérialiser des fonctions via pickle pour les transmettre sur un réseau a échoué dans certains environnements : une lambda pickled ne peut pas être transférée entre des machines avec des configurations/versions de Python différentes.