8
votes

Python 3: code patché de singe non ré-importable par multiprocession

en bref

Comment puis-je module de patch de singe A du module B lorsque les fonctions de Module A sont censées être importables afin que je puisse exécuter les fonctions de module A avec le package de bibliothèque standard

Fond

Un client a demandé un correctif qui ne s'appliquera pas à aucun de nos autres clients, j'ai donc créé une nouvelle succursale et a écrit un module séparé pour que cela puisse faire la fusion dans les modifications de la branche principale facile. Pour maintenir la compatibilité en arrière du client avec le comportement de pré-hotfix, j'ai implémenté le correctif comme paramètre configurable de l'application. Ainsi, je ne voulais pas remplacer mon ancien code - juste le correctif lorsque le réglage a été allumé. Je l'ai fait par Singe patching .

Structure de code

Le module __ Main __ dans le fichier de configuration. Si la configuration tourne sur le commutateur du correctif, __ MAIN __ PATCHES MON MODULE MOTEUR En remplaçant quelques fonctions avec code défini dans le module hotfix En substance, la fonction étant remplacée est le fonction de la touche à une fonction de maximisation . Le module Moteur Charge ultérieurement une piscine de MultiProcessing travailleurs.

Le problème

Une fois qu'un multiprocessionnaire travailleur commence, la première chose multiprocessionnaire est-ce que Ré-importateurs * Le module Moteur et recherche la fonction de clé que __ principal __ avait essayé de remplacer (alors multiprocession contrôle des mains à mon code et l'algorithme de maximisation commence). Puisque moteur est en cours de ré-importé par un nouveau processus et le nouveau processus ne réexécute pas __ principal __ (où le fichier de configuration est lu) car cela provoquerait une infinie Boucle, il ne sait pas au ré-singe-patch moteur .

la question

Comment puis-je maintenir la modularité dans mon code (c'est-à-dire de garder le code de correctif dans un module séparé) et profitez toujours du package multiprocessing de Python's

* Remarque Mon code doit fonctionner sur Windows (pour mon client) et UNIX (pour ma santé mentale ...)


5 commentaires

+1, question joliment formatée. Mais pas multiprocessionnaire REIMPORT __ Main __ dans les processus enfants?


@nneonneo, oui mais respirant __ Main __. Main () entraînerait une boucle infinie.


Bien-sûr. Mais vous ne pouvez pas avoir séparé read_config et principale () méthodes et appelez read_config mais pas principal () ?


Comment obtenir __ principal __ pour déterminer s'il est chargé sous forme de multiprocessionnaire travailleur ou de la ligne de commande?


Voir ma réponse. Je crois que cela devrait le faire pour vous.


3 Réponses :


0
votes

On dirait que vous allez devoir modifier moteur.py pour vérifier un fichier de configuration et avoir le correctif lui-même s'il est nécessaire.

Travailler sur UNIX et Windows Moteur peut conserver une variable global config_done pour décider si elle doit vérifier à nouveau pour le fichier de configuration.


0 commentaires

1
votes

Cela ressemble à un endroit où la correction de singe ne fonctionnera tout simplement pas. Il est plus facile de simplement extraire les fonctions en question à un modules distincts et d'importer du moteur à partir de là. Peut-être que vous pouvez avoir un paramètre de configuration de l'endroit où les importer de.

Une autre façon de modulariser ceci est d'utiliser une sorte d'architecture de composants, comme ZCA . Cette dernière option est ce que j'irais avec, mais c'est parce que je suis habitué à cela, donc il n'y a pas d'apprentissage supplémentaire pour moi.


0 commentaires

1
votes

Pour le faire fonctionner sur un système d'exploitation UNIX / Linux qui a Fourche () , vous n'avez pas besoin de faire quelque chose de spécial car le nouveau processus a accès aux mêmes classes (patchées de singe). comme le parent.

Pour le faire fonctionner sous Windows, demandez à votre __ Main __ Lire la configuration à l'importation (mettre le read_config / patch_engine appel à la portée globale ), mais faire le multitraitement (exécution du moteur) dans un si __name__ == '__main __' garde.

Ensuite, le code de lecture de lecture sera effectué chaque fois que __ principal __ est importé (à partir de la ligne de commande ou à partir d'un multiprocessionnaire réimport), mais le Si __name__ == '__Main __' Le code n'est effectué que lorsque votre script est appelé à partir de la ligne de commande (puisque __ Main __ est réimporté sous un nom différent dans le processus d'enfant).


0 commentaires