web-dev-qa-db-fra.com

Comment remplacer une importation Python?

Je travaille sur pypreprocessor qui est un préprocesseur qui prend des directives de style c et j'ai pu le faire fonctionner comme un préprocesseur traditionnel (il est auto-consommant et exécute du code post-traité sur le- fly) sauf qu'il interrompt les importations de bibliothèque.

Le problème est le suivant: le préprocesseur parcourt le fichier, le traite, sort dans un fichier temporaire et exécute () le fichier temporaire. Les bibliothèques importées doivent être traitées un peu différemment, car elles ne sont pas exécutées, mais elles sont plutôt chargées et rendues accessibles au module appelant.

Ce que je dois être en mesure de faire est de: interrompre l'importation (puisque le préprocesseur est en cours d'exécution au milieu de l'importation), charger le code post-traité en tant que tempModule et remplacer l'importation d'origine par tempModule pour tromper le script appelant avec l'import à croire que le tempModule est le module d'origine.

J'ai cherché partout et jusqu'à présent et je n'ai pas de solution.

Cette question Stack Overflow est la plus proche que j'ai vue jusqu'à présent pour fournir une réponse: Override namespace in Python

Voici ce que j'ai.

# Remove the bytecode file created by the first import
os.remove(moduleName + '.pyc')

# Remove the first import
del sys.modules[moduleName]

# Import the postprocessed module
tmpModule = __import__(tmpModuleName)

# Set first module's reference to point to the preprocessed module
sys.modules[moduleName] = tmpModule

moduleName est le nom du module d'origine et tmpModuleName est le nom du fichier de code post-traité.

La partie étrange est que cette solution fonctionne toujours complètement comme si le premier module terminé se chargeait normalement; sauf si vous supprimez la dernière ligne, vous obtenez une erreur de module introuvable.

J'espère que quelqu'un sur Stack Overflow en sait beaucoup plus sur les importations que moi, car celui-ci m'a déconcerté.

Remarque: Je n'accorderai qu'une solution, ou, si cela n'est pas possible en Python; l'explication la meilleure et la plus détaillée des raisons pour lesquelles cela n'est pas impossible.

Mise à jour: Pour toute personne intéressée, voici le code de travail.

if imp.lock_held() is True:
    del sys.modules[moduleName]
    sys.modules[tmpModuleName] = __import__(tmpModuleName)
    sys.modules[moduleName] = __import__(tmpModuleName)

La partie 'imp.lock_held' détecte si le module est chargé en tant que bibliothèque. Les lignes suivantes font le reste.

34
Evan Plaice

Est-ce que cela répond à votre question? La deuxième importation fait l'affaire.

Mod_1.py

def test_function():
    print "Test Function -- Mod 1"

Mod_2.py

def test_function():
    print "Test Function -- Mod 2"

Test.py

#!/usr/bin/python

import sys

import Mod_1

Mod_1.test_function()

del sys.modules['Mod_1']

sys.modules['Mod_1'] = __import__('Mod_2')

import Mod_1

Mod_1.test_function()
35
Ron

Pour définir un comportement d'importation différent ou pour inverser totalement le processus d'importation, vous devrez écrire des crochets d'importation. Voir PEP 302 .

Par exemple,

import sys

class MyImporter(object):

    def find_module(self, module_name, package_path):
        # Return a loader
        return self

    def load_module(self, module_name):
        # Return a module
        return self

sys.meta_path.append(MyImporter())

import now_you_can_import_any_name
print now_you_can_import_any_name

Il génère:

<__main__.MyImporter object at 0x009F85F0>

Donc, fondamentalement, il retourne un nouveau module (qui peut être n'importe quel objet), dans ce cas lui-même. Vous pouvez l'utiliser pour modifier le comportement d'importation en renvoyant processe_xxx lors de l'importation de xxx.

IMO: Python n'a pas besoin de préprocesseur. Tout ce que vous accomplissez peut être accompli dans Python lui-même en raison de sa nature très dynamique, par exemple, en prenant l'exemple de débogage, qu'est-ce qui ne va pas avec le début du fichier

debug = 1

et ensuite

if debug:
   print "wow"

?

12
Anurag Uniyal

Dans Python 2 il y a le module imputil qui semble fournir la fonctionnalité que vous recherchez, mais a été supprimé dans python 3. Ce n'est pas très bien documenté mais contient un exemple de section qui montre comment vous pouvez remplacer les fonctions d'importation standard.

Pour Python 3 il y a le module importlib (introduit dans Python 3.1) qui contient des fonctions et des classes pour modifier la fonctionnalité d'importation de toutes sortes de façons. Il devrait convenir de connecter votre préprocesseur au système d'importation.

0
sth