Je veux faire un patch monkey seulement en partie en toute sécurité avec Python

Qu'est-ce que Monkey Patch?

Les patchs Monkey étendent ou modifient le code de langage dynamique (par exemple Smalltalk, JavaScript, Objective-C, Ruby, Perl, Python, Groovy, etc.) au moment de l'exécution sans modifier le code source d'origine. Comment faire.

[Voir wiki](https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%B3%E3%82%AD%E3%83%BC%E3%83%91%E3% 83% 83% E3% 83% 81)

Matière

Le rond n'est plus arrondi en Python 3

print round(2.5) # => 3.0
print(round(2.5)) # => 2

Il semble que la fonction round soit traitée comme une virgule flottante depuis python3. Pour que vous puissiez l'utiliser en arrondissant !!

Code d'arrondi

def custom_round(x, d=0):
    import math
    p = 10 ** d
    return float(math.floor((x * p) + math.copysign(0.5, x)))/p
print(custom_round(2.5)) #=> 3.0

URL de référence

↓ ↓ Je veux écrire comme ça ↓ ↓

sample.py


import setting
print(round(2.5)) #=> 3.0

Générer setting.py

1. Monkey patch pour le moment

setting.py


import builtins #Les fonctions intégrées sont intégrées
def custom_round(x, d=0):
    import math
    p = 10 ** d
    return float(math.floor((x * p) + math.copysign(0.5, x)))/p
builtins.round = custom_round # monkey patch

sample.py


import setting
print(round(2.5)) #=> 3.0
J'ai pensé que c'était un succès car il était affiché

sample.py


import setting
print(round(2.5)) #=> 3.0
import sample2

sample2.py


print(round(2.5)) #=> 3.0
=> Pas sûr !!!!?

2. Accrochez l'espace de nom de l'appelant à partir de la trace de pile

python


import inspect, imp
import builtins
def custom_round(x, d=0):
    import math
    p = 10 ** d
    return float(math.floor((x * p) + math.copysign(0.5, x)))/p

frame = [frame for (frame, filename, _, _, _,_) in 
             inspect.getouterframes(inspect.currentframe())[1:] 
                 if not 'importlib' in filename and not __file__ in filename][0]
        #Parce qu'il y a des cas où importlib est utilisé pour obtenir l'appelant et importer.
frame.f_locals['round'] = custom_round

sample.py


import setting
print(round(2.5)) #=> 3.0
import sample2

sample2.py


print(round(2.5)) #=> 2

Remplacement de la dernière ligne.py


# ${module} :Module cible, ${function} :Fonction cible
replacing = imp.load_module('temp', *imp.find_module(${module}))
setattr(replacing, '${function}', ${fonction personnalisée})
frame.f_locals[${module}] = replacing
Je me demande si le fichier a été séparé ... Le processus de paramétrage n'est pas effectué dans sample2 ...

sample.py


import setting
print(round(2.5)) #=> 3.0
import sample2

sample2.py


import setting
print(round(2.5)) #=> 2

=> Le module importé une fois est conservé dans sys.modules, et dans la seconde importation, il est référencé à partir de sys.module et le code n'est pas appelé.

3. Remplacez directement builtins.import et appelez la fonction monkey patch au moment de l'importation.

setting.py


import inspect, imp
import builtins
def custom_round(x, d=0):
    import math
    p = 10 ** d
    return float(math.floor((x * p) + math.copysign(0.5, x)))/p

def hooking():
    frame = [frame for (frame, filename, _, _, _,_) in 
             inspect.getouterframes(inspect.currentframe())[1:] 
                 if not 'importlib' in filename and not __file__ in filename][0]
        #Parce qu'il y a des cas où importlib est utilisé pour obtenir l'appelant et importer.
    frame.f_locals['round'] = custom_round

class Importer(object):
    old_import = __import__
    def new_import(self, *args, **kwargs):
        if args[0] == __name__: hooking() 
        return self.old_import(*args, **kwargs)

hooking()
import builtins
builtins.__import__ = Importer().new_import

sample.py


import setting
print(round(2.5)) #=> 3.0
import sample2

sample2.py


import setting
print(round(2.5)) #=> 3.0

Résumé

Enfin, j'ai pu implémenter un patch monkey uniquement avec le module où le paramètre d'importation est écrit.

Recommended Posts

Je veux faire un patch monkey seulement en partie en toute sécurité avec Python
Je veux faire le test de Dunnett en Python
Je veux créer une fenêtre avec Python
Je souhaite intégrer une variable dans une chaîne Python
Je veux écrire en Python! (2) Écrivons un test
Je veux échantillonner au hasard un fichier avec Python
Je veux faire quelque chose avec Python à la fin
Je veux faire quelque chose comme sort uniq en Python
Je veux ajouter un joli complément à input () en python
Je veux imprimer dans la notation d'inclusion
Je veux créer un environnement Python
Je veux résoudre APG4b avec Python (seulement 4.01 et 4.04 au chapitre 4)
Je souhaite rechercher le texte intégral avec elasticsearch + python
[Couches Python / AWS Lambda] Je souhaite réutiliser uniquement le module dans AWS Lambda Layers
Je veux faire un jeu avec Python
Je souhaite convertir une table convertie en PDF en Python en CSV
Je veux fusionner des dictionnaires imbriqués en Python
Je veux colorer une partie de la chaîne Excel avec Python
Je veux écrire dans un fichier avec Python
Je veux afficher la progression en Python!
Je souhaite créer une file d'attente prioritaire pouvant être mise à jour avec Python (2.7)
Le programme Python est lent! Je veux accélérer! Dans ce cas ...
Je veux répéter plusieurs fois un générateur Python
Je veux générer rapidement UUID (memo memo) ~ Edition Python ~
Je veux faire la transition avec un bouton sur le ballon
Même avec JavaScript, je veux voir Python `range ()`!
J'ai essayé d'implémenter un pseudo pachislot en Python
[Python] Je veux faire d'une liste imbriquée un taple
Je veux écrire en Python! (3) Utiliser des simulacres
Je veux utiliser le jeu de données R avec python
Je veux faire fonctionner un ordinateur quantique avec Python
Je veux manipuler des chaînes dans Kotlin comme Python!
[Python] Je souhaite utiliser uniquement l'index lors de la mise en boucle d'une liste avec une instruction for
Je souhaite utiliser une source de données python dans Re: Dash pour obtenir les résultats de la requête.
[Python] Je souhaite obtenir un ensemble commun entre numpy
Je veux démarrer beaucoup de processus à partir de python
J'ai essayé "Comment obtenir une méthode décorée en Python"
Je souhaite envoyer un message de Python à LINE Bot
J'ai fait un chronomètre en utilisant tkinter avec python
Je veux pouvoir exécuter Python avec VS Code
[Python] Comment faire PCA avec Python
Je veux déboguer avec Python
Voulez-vous attendre un usage général avec Python Selenium?
Que faire si vous obtenez moins zéro en Python
Configuration MacBookPro Après tout, je veux faire une installation propre
J'ai écrit une fonction pour charger le script d'extension Git en Python
J'ai essayé de mettre en œuvre un jeu de dilemme de prisonnier mal compris en Python
Si vous souhaitez affecter une exportation csv à une variable en python
Je voulais faire quelque chose comme la pipe d'Elixir en Python
[Introduction] Je veux créer un robot Mastodon avec Python! 【Débutants】
J'ai écrit un script pour extraire les liens de pages Web en Python
Je veux créer un fichier pip et le refléter dans le menu fixe
J'ai essayé d'implémenter PLSA en Python
J'ai essayé d'implémenter la permutation en Python
Faites une visite Euler non récursive en Python
J'ai fait un programme de gestion de la paie en Python!
Comment faire R chartr () en Python
J'ai essayé d'implémenter PLSA dans Python 2
Je veux utiliser jar de python