


Comment développer Monkey Patch en programmation Python
La méthode Monkey Patch fait référence à l'ajout de code pendant le processus d'exécution du programme en ajoutant des classes ou des modules sans modifier le code original du programme. Ce qui suit est une explication plus détaillée de la méthode de développement Monkey Patch dans la programmation Python. L'application du
Monkey patch consiste à modifier le code existant au moment de l'exécution pour atteindre l'objectif du hot patch. Cette technique est largement utilisée dans Eventlet pour remplacer des composants de la bibliothèque standard, tels que les sockets. Tout d’abord, jetons un coup d’œil à l’implémentation la plus simple de Monkey Patch.
class Foo(object): def bar(self): print 'Foo.bar' def bar(self): print 'Modified bar' Foo().bar() Foo.bar = bar Foo().bar()
Étant donné que l'espace de noms en Python est ouvert et implémenté via dict, il est facile d'atteindre l'objectif de l'application de correctifs.
Espace de noms Python
Python a plusieurs espaces de noms, à savoir
locals
-
globaux
builtin
Les variables définies dans les fonctions appartiennent aux variables locales, tandis que les fonctions définies dans les modules appartiennent aux variables globales.
Importation de module Python et recherche de nom
Lorsque nous importons un module, Python fera les choses suivantes
Importer un module
et ajoutez l'objet module à sys.modules. Les importations ultérieures du module seront obtenues directement à partir du dict
. L'objet module est ajouté au dict global
Lorsque nous référençons un module, il sera recherché à partir des globaux. Si nous voulons remplacer un module standard ici, nous devons faire les deux choses suivantes
Ajouter notre propre module à sys.modules et remplacer le module d'origine. Si le module remplacé n'a pas été chargé, nous devons d'abord le charger, sinon le module standard sera chargé la première fois. (Il existe un hook d'importation disponible ici, mais cela nous oblige à implémenter le hook nous-mêmes. Nous pouvons également utiliser cette méthode pour hooker l'importation de module)
Si le module remplacé fait référence à d'autres modules, alors nous devons également le remplacer, mais ici, nous pouvons modifier le dict des globals et ajouter notre module aux globals pour accrocher ces modules référencés.
Implémentation d'Eventlet Patcher
Jetons maintenant un coup d'œil au code d'appel de Patcher dans l'eventlet. Ce code crée un patch singe pour la ftplib standard et remplace le GreenSocket standard de l'événement. événementlet.
from eventlet import patcher # *NOTE: there might be some funny business with the "SOCKS" module # if it even still exists from eventlet.green import socket patcher.inject('ftplib', globals(), ('socket', socket)) del patcher inject函数会将eventlet的socket模块注入标准的ftplib中,globals dict被传入以做适当的修改。 让我们接着来看一下inject的实现。 __exclude = set(('__builtins__', '__file__', '__name__')) def inject(module_name, new_globals, *additional_modules): """Base method for "injecting" greened modules into an imported module. It imports the module specified in *module_name*, arranging things so that the already-imported modules in *additional_modules* are used when *module_name* makes its imports. *new_globals* is either None or a globals dictionary that gets populated with the contents of the *module_name* module. This is useful when creating a "green" version of some other module. *additional_modules* should be a collection of two-element tuples, of the form (, ). If it's not specified, a default selection of name/module pairs is used, which should cover all use cases but may be slower because there are inevitably redundant or unnecessary imports. """ if not additional_modules: # supply some defaults additional_modules = ( _green_os_modules() + _green_select_modules() + _green_socket_modules() + _green_thread_modules() + _green_time_modules()) ## Put the specified modules in sys.modules for the duration of the import saved = {} for name, mod in additional_modules: saved[name] = sys.modules.get(name, None) sys.modules[name] = mod ## Remove the old module from sys.modules and reimport it while ## the specified modules are in place old_module = sys.modules.pop(module_name, None) try: module = __import__(module_name, {}, {}, module_name.split('.')[:-1]) if new_globals is not None: ## Update the given globals dictionary with everything from this new module for name in dir(module): if name not in __exclude: new_globals[name] = getattr(module, name) ## Keep a reference to the new module to prevent it from dying sys.modules['__patched_module_' + module_name] = module finally: ## Put the original module back if old_module is not None: sys.modules[module_name] = old_module elif module_name in sys.modules: del sys.modules[module_name] ## Put all the saved modules back for name, mod in additional_modules: if saved[name] is not None: sys.modules[name] = saved[name] else: del sys.modules[name] return module
Les commentaires expliquent clairement l'intention du code. Le code est relativement facile à comprendre. Il existe une fonction __import__, qui fournit un nom de module (chaîne) pour charger un module. Le nom que nous fournissons lors de l’importation ou du rechargement est un objet.
if new_globals is not None: ## Update the given globals dictionary with everything from this new module for name in dir(module): if name not in __exclude: new_globals[name] = getattr(module, name)
La fonction de ce code est d'ajouter des objets en ftplib standard au module ftplib de eventlet. Parce que nous avons appelé inject dans eventlet.ftplib et transmis les globals, et dans inject, nous __importons manuellement le module et n'avons obtenu qu'un seul objet de module, donc les objets du module ne seront pas ajoutés aux globals et devront être ajoutés manuellement.
La raison pour laquelle from ftplib import * n'est pas utilisé ici est probablement parce qu'il ne peut pas remplacer complètement ftplib. Parce que from...import * importera les symboles publics selon la liste __all__ dans __init__.py, et de cette manière, les symboles privés commençant par un trait de soulignement ne seront pas importés et une correction complète ne pourra pas être réalisée.
Pour plus d'articles liés aux méthodes de développement de Monkey Patch dans la programmation Python, veuillez faire attention au site Web PHP chinois !

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds





Solution aux problèmes d'autorisation Lors de la visualisation de la version Python dans Linux Terminal Lorsque vous essayez d'afficher la version Python dans Linux Terminal, entrez Python ...

Comment enseigner les bases de la programmation novice en informatique dans les 10 heures? Si vous n'avez que 10 heures pour enseigner à l'informatique novice des connaissances en programmation, que choisissez-vous d'enseigner ...

Lorsque vous utilisez la bibliothèque Pandas de Python, comment copier des colonnes entières entre deux frames de données avec différentes structures est un problème courant. Supposons que nous ayons deux dats ...

Comment éviter d'être détecté lors de l'utilisation de FiddlereVerywhere pour les lectures d'homme dans le milieu lorsque vous utilisez FiddlereVerywhere ...

Comment Uvicorn écoute-t-il en permanence les demandes HTTP? Uvicorn est un serveur Web léger basé sur ASGI. L'une de ses fonctions principales est d'écouter les demandes HTTP et de procéder ...

Dans Python, comment créer dynamiquement un objet via une chaîne et appeler ses méthodes? Il s'agit d'une exigence de programmation courante, surtout si elle doit être configurée ou exécutée ...

Utilisation de Python dans Linux Terminal ...

Fastapi ...
