Python Discussion 2 - Python 3.12 Hotfix
Enregistrer comment implémenter une mise à jour en direct dans Python 3.12.
Mise à jour en direct.
Le "Hot Reload" est une technologie qui permet de mettre à jour un programme sans avoir besoin de le redémarrer. Cette technique est largement utilisée dans l'industrie du jeu vidéo. Lorsque les développeurs corrigent des problèmes de jeu, ils utilisent souvent des mises à jour silencieuses, appelées "Hot Reload", afin de ne pas perturber les joueurs.
Mise à jour dynamique des modules Python
Python is dynamically typed, everything is an object, and it's capable of hot updates. We can roughly divide the objects that need to be hot updated in Python into two types: data and functions.
Les données peuvent être comprises comme des valeurs ou des paramètres dans un jeu, comme le niveau du joueur, l'équipement, etc. Certaines données ne devraient pas être mises à jour dynamiquement (comme le niveau actuel du joueur, l'équipement qu'il possède), tandis que d'autres sont destinées à être mises à jour dynamiquement (comme les paramètres de base de l'équipement, les paramètres de base des compétences, le texte sur l'interface utilisateur, etc.).
Les fonctions peuvent être comprises comme la logique du jeu, c'est essentiellement ce que nous voulons mettre à jour fréquemment, les erreurs logiques doivent généralement être corrigées en mettant à jour les fonctions.
Ci-dessous, examinons en détail les méthodes pour mettre à jour Python 3.12 en temps réel.
Hotfix
Nous appelons le premier méthode "Hotfix", qui consiste à exécuter un code Python spécifique (que ce soit le programme client ou serveur), pour mettre à jour les données et les fonctions en temps réel. Un exemple simple de code Hotfix pourrait être le suivant :
# hotfix code
# hotfix data
import weapon_data
weapon_data.gun.damage = 100
# hotfix func
import player
def new_fire_func(self, target):
target.health -= weapon_data.gun.damage
# ...
player.Player.fire_func = new_fire_func
Le code ci-dessus montre simplement comment écrire un correctif rapide. Une fois que les données / fonctions ont été modifiées, le programme lira les nouvelles données / fonctions lors des visites ultérieures pour les exécuter.
Si tu es attentif, tu pourrais te demander : que se passe-t-il si d'autres parties du code font référence à ces données et fonctions à modifier ?
# attack.py module
player_fire = player.Player.fire_func
def player_attack_by_gun(player, target):
player_fire(player, target)
# ...
La réponse est que le correctif rapide précédent ne s'applique pas à cette situation, la fonction fire_func
agit comme une copie supplémentaire dans un autre module, et l'appel de cette fonction dans ce module se fait sur une copie. Ainsi, les modifications apportées au corps de la fonction ne sont pas répercutées sur la copie.
Il est donc essentiel de veiller à réduire autant que possible les références de données et de fonctions au niveau du module dans le code général, afin d'éviter les cas où ce genre de correctif d'urgence ne fonctionne pas. Si le code est déjà rédigé de cette manière, il faudra fournir des efforts supplémentaires lors de l'application de ce correctif.
Après avoir apporté des correctifs au niveau des données / fonctions principales, veillez à modifier également les références supplémentaires. Ces modifications supplémentaires sont souvent négligées, c'est pourquoi il est préférable de suivre les normes de codage pour éviter autant que possible les écritures avec plusieurs références.
Dans l'ensemble, les correctifs rapides peuvent répondre aux besoins essentiels des mises à jour fréquentes, mais présentent également les problèmes suivants :
Si les données / fonctions sont explicitement référencées par d'autres modules, des correctifs chauds supplémentaires doivent être appliqués à ces modules. Si un grand nombre de données/fonctions nécessitent des correctifs urgents, le code des correctifs deviendra très volumineux, ce qui rendra la maintenance plus difficile et augmentera les risques d'erreurs.
Reload
Ce chapitre est disponible en source à partir d'ici : python_reloader
Ce que nous préférons vraiment, c'est la mise à jour automatique en temps réel, sans avoir à écrire de correctifs d'urgence supplémentaires. Il suffit de mettre à jour les fichiers de code, d'exécuter une fonction de rechargement pour remplacer automatiquement les nouvelles fonctions et les nouvelles données. Nous appelons cette fonctionnalité de mise à jour automatique en temps réel "Rechargement".
Python3.12 introduces the importlib.reload function, which allows for module reloading, but it is a full reload and returns a new module object. However, references in other modules are not automatically updated. This means that if other modules import the reloaded module, they will still access the old module object. This feature doesn't offer much advantage over our Hotfix, especially since it's a full reload of the module and we cannot control which data should be preserved. We want to implement our own Reload function to meet these requirements:
Remplacement automatique de la fonction, les références à l'ancienne fonction restent valides et exécutent le contenu de la nouvelle fonction. Remplacement automatique des données, permettant également un remplacement partiel contrôlable. Conserver les références aux anciens modules pour accéder au nouveau contenu à travers ces anciens modules. Les modules nécessitant un rechargement doivent être contrôlables.
(https://docs.python.org/zh-cn/3/reference/import.html?highlight=meta_path#the-meta-path)Translate these text into French language:
。
La variable sys.meta_path permet de définir notre propre objet de recherche de chemin d'accès, par exemple, si nous appelons notre objet de recherche utilisé pour le rechargement "reload_finder", ce dernier doit mettre en œuvre une fonction "find_spec" et renvoyer un objet "spec". Une fois que Python obtient l'objet "spec", il exécute successivement "spec.loader.create_module" et "spec.loader.exec_module" pour terminer l'importation du module.
Si nous exécutons de nouveaux codes de module dans ce processus et copions les fonctions et les données nécessaires du nouveau module dans l'ancien module, nous pouvons atteindre l'objectif de rechargement :
Comme indiqué précédemment, find_spec
charge le code source le plus récent du module, exécute ce code dans le __dict__
de l'ancien module, puis nous utilisons ReloadModule
pour gérer les références et les remplacements de classes / fonctions / données. L'objectif de MetaLoader
est d'adapter le mécanisme de meta_path en renvoyant à la machine virtuelle Python les objets de module que nous avons traités.
Une fois le processus de chargement terminé, examinons maintenant l'implémentation générale de ReloadModule
.
La classe ReloadDict
différenciera et traitera les objets de types différents.
Si c'est une classe, appelez ReloadClass
, elle renverra la référence de l'ancien module et mettra à jour les membres de la classe.
Si c'est une fonction/méthode, appeler ReloadFunction
renverra la référence du module précédent et mettra à jour les données internes de la fonction.
Si c'est un ensemble de données et qu'il doit être conservé, alors il reviendra en arrière : new_dict[attr_name] = old_attr
Maintenez les autres citations en cours comme nouvelles.
Remove functions that do not exist in the new module.
Les codes spécifiques de ReloadClass
et ReloadFunction
ne seront pas détaillés ici. Si vous êtes intéressé, vous pouvez consulter directement le code source。
Le processus complet de rechargement peut être résumé ainsi : donner un coup de jeune à une vieille histoire. Pour maintenir la validité des modules/fonctions/classes de modules/données de modules, il est nécessaire de conserver les références des objets originaux (leur enveloppe), et ensuite de mettre à jour spécifiquement leurs données internes. Par exemple, pour les fonctions, on met à jour __code__
, __dict__
,` et autres données. Lors de l'exécution de la fonction, elle passera à l'exécution du nouveau code.
Résumé
Ce texte présente en détail les deux méthodes de mise à jour à chaud de Python3, chacune ayant ses propres cas d'utilisation. J'espère que cela vous sera utile. N'hésitez pas à poser des questions ou à échanger à tout moment.
Original: https://wiki.disenone.site/fr
This post is protected by CC BY-NC-SA 4.0 agreement, should be reproduced with attribution.
Visitors. Total Visits. Page Visits.
Ce message a été traduit en utilisant ChatGPT, veuillez en 反馈Identifier toute omission.