Comment obtenir une référence à un module à l'intérieur du module lui-même?

159

Comment puis-je obtenir une référence à un module à partir de ce module? Aussi, comment puis-je obtenir une référence au package contenant ce module?

Ram Rachum
la source
7
Je soupçonne que vous posez peut-être cette question parce que vous avez une variable dans la portée du module (par exemple, BLAH = 10 en dehors d'une fonction ou d'une classe), puis une variable de classe / fonction nommée BLAH et que vous souhaitez différencier. Une question valable ici est: est-ce nécessaire? Les règles de portée sont notoirement sujettes à des erreurs, en particulier de la part de «l'idiot» qui récupère votre code après vous (c'est-à-dire vous, 6 mois plus tard). Des trucs comme celui-ci sont rarement nécessaires; J'essaie de les éviter complètement car ils sont souvent déroutants et modifiés à tort par la suite.
Kevin
2
@ KevinJ.Rice "l'idiot" qui récupère votre code après vous (ie, vous, 6 mois plus tard) "a fait ma journée!
arctelix
8
Qui se soucie de savoir pourquoi il pose la question? Il existe de nombreuses raisons valables de le faire.
Christopher Barber
Doit être fermé. Trop utile.
mlvljr

Réponses:

212
import sys
current_module = sys.modules[__name__]
truppo
la source
3
sauf que cela ne sera pas tout à fait correct si le module est rechargé; Je ne pense pas qu'il y ait un endroit où une référence est garantie d'être conservée, si c'était le cas, le rechargement ne fonctionnerait pas vraiment, non?
Dima Tisnek
14
Le rechargement réutilise le même objet module; aucun nouvel objet module n'est créé, il est donc toujours correct face au rechargement.
bukzor
18

Une autre technique, qui n'importe pas le module sys, et sans doute - dépend de votre goût - plus simple:

current_module = __import__(__name__)

Sachez qu'il n'y a pas d'importation. Python importe chaque module une seule fois.

Uri
la source
Cela semble être une très bonne façon d'éviter d'importer sys. En plus d'être un peu contre-intuitif à lire, y a-t-il des inconvénients potentiels à cette approche?
JeremyDouglass
@JeremyDouglass. Pas que je sache. import est une fonction intégrée légitime, documentée (la seule fonction xx ). Vous pouvez le remplacer par le package 'importlib' (vous devrez l'importer). Peut-être que - ne m'est jamais arrivé - vous pourriez avoir un problème avec l'importation relative / absolue, si un module avec le même nom est disponible dans sys.path, auquel cas vous pouvez le résoudre avec l'argument 'level' de la fonction.
Uri
16

Si vous avez une classe dans ce module, la __module__propriété de la classe est le nom du module de la classe. Ainsi, vous pouvez accéder au module via sys.modules[klass.__module__]. Cela fonctionne également pour les fonctions.

Michael
la source
4
En fait, il semble que (au moins) pour une fonction, la __module__propriété ne soit pas un module, mais une chaîne; ainsi a inspect.getabsfile(func.__module__)échoue avec " TypeError: 'os' n'est pas un module, une classe, une méthode, une fonction, une traceback, un cadre ou un objet de code "; tandis que inspect.getabsfile(sys.modules[o.__module__])semble passer.
sdaau
12

Vous pouvez obtenir le nom du module actuel en utilisant __name__

La référence du module se trouve dans le sys.modulesdictionnaire.

Voir la documentation Python

pkit
la source
1

Vous pouvez le transmettre de l'extérieur:

mymod.init(mymod)

Pas idéal mais cela fonctionne pour mon cas d'utilisation actuel.

Sam Watkins
la source