2011-10-24 12 views
9

¿Cómo puedo averiguar qué archivo está importando un archivo en particular en python?¿Cómo saber quién me está importando en python?

Consideremos el siguiente ejemplo:

#a.py 
import cmn 
.... 

#b.py 
import cmn 
... 

#cmn.py 
#Here, I want to know which file (a.py or b.py) 
#is importing this one. 
#Is it possible to do this? 
... 

Todos los archivos a.py, b.py y cmn.py están en el mismo directorio.

¿Por qué quiero hacer esto?
En C/C++, tienen función de inclusión. Lo que quiero hacer puede iluminarse con el código C/C++.

//a.cpp 
.... 
#define SOME_STUFF .... 
#include "cmn.h" 

//b.cpp 
... 
#define SOME_STUFF .... 

#include "cmn.h" 

//cmn.h 
//Here, I'll define some functions/classes that will use the symbol define 
//in the a.cpp or b.cpp 
... 
....code refer to the SOME_STUFF..... 

en C/C++, podemos utilizar este método para reutilizar sourecode.

Ahora regrese a mi código python.
Cuando a.py import cmn.py, espero ejecutar cmn.py y el cmn.py se referirá al símbolo definido en el a.py.
Cuando b.py import cmn.py, espero ejecutar cmn.py y el cmn.py se referirá al símbolo definido en b.py.

+3

Las bibliotecas no deben depender de quién las importa, por lo que realmente no debería importar. –

+4

@MichaelAaronSafyan tiene razón. Sin embargo, * se puede * hacer, como lo demuestro aquí: http://stackoverflow.com/questions/7025538/in-python-if-a-module-calls-upon-another-modules-functions-is-it- posible-para/7025963 # 7025963. Sin embargo ... ¿cuál es el problema * real * que estás tratando de resolver? – Johnsyweb

+0

¿Qué estás tratando de lograr? Tal vez haya una forma alternativa de lograrlo sin acoplar sus archivos de esta manera. –

Respuesta

10

El namedtuple código en el colecciones módulo tiene un ejemplo de cómo (y cuándo) para hacer esto:

#cmn.py 
import sys 
print 'I am being imported by', sys._getframe(1).f_globals.get('__name__') 

Una limitación de este enfoque es que el módulo más externa siempre se denomina __main__. Si ese es el caso, el nombre del módulo más externo se puede determinar a partir de sys.argv[0].

Una segunda limitación es que si el código que usa sys._getframe está en el alcance del módulo, solo se ejecuta en la primera importación de cmn.py. Debería llamar a una función de algún tipo después de las importaciones si desea controlar todas las importaciones del módulo.

+0

Tenga en cuenta que la instrucción de impresión solo se ejecuta en la primera importación del módulo. Si desea capturar todas las importaciones, debe invocar una función desde cmn.py después de cada importación o usar un enlace de importación. –

+1

¿Cómo se implementaría algo similar para py3? – Rizo

+0

Éste trabajó para ambas versiones: https://stackoverflow.com/a/7151403/379159 – simno

3

Bueno, este es un tipo de cosa extraña que hacer. No ha explicado por qué desea saber qué está importando su módulo, por lo que no puedo ayudarle a resolver su problema. Tampoco ha explicado cómo o cuándo quiere saber el módulo de importación.

def who_imports(studied_module): 
    for loaded_module in sys.modules.values(): 
     for module_attribute in dir(loaded_module): 
      if getattr(loaded_module, module_attribute) is studied_module: 
       yield loaded_module 

Esto le dará un iterador sobre todos los módulos que usan su módulo como un objeto de nivel superior. No encontrará módulos que hagan from cmn import *, y la lista cambiará con el tiempo.

>>> import os 
>>> for m in who_imports(os): 
...  print m.__name__ 
... 
site 
__main__ 
posixpath 
genericpath 
posixpath 
linecache 
+0

También parece que no manejaría 'importar foo como barra'. –

+1

@TavisRudd: realmente maneja 'import foo as bar':' who_imports (foo) 'devolverá el módulo que realizó la importación. Esto se debe a que la prueba se realiza en objetos 'module' (a través de' is module'), y no en los nombres de los módulos. Sin embargo, tenga en cuenta que los nombres de los módulos informados son los nombres originales (el programa que contiene la importación dará el nombre 'foo' si se llama a' who_imports (bar) '). – EOL

+0

@DietrichEpp: +1: forma limpia de responder la pregunta. Sin embargo, la función 'who_imports()' podría optimizarse. Por ejemplo, muchos 'sys.modules.values ​​()' son 'Ninguno' y podrían omitirse. – EOL

1

Necesitará instalar un gancho de importación que rastree todas las importaciones. Ver PEP 302 y http://docs.python.org/dev/py3k/library/importlib.html. Sin embargo, como lo señalan los comentarios anteriores, probablemente exista una mejor manera de estructurar su código.

Cuestiones relacionadas