2009-11-28 19 views
18

Tengo problemas de importación cíclicos agregando algún código nuevo a una aplicación muy grande, y estoy tratando de determinar qué archivos son las causas más probables para esto. ¿Hay alguna forma de rastrear qué archivos importan qué archivos? Hice un poco de búsqueda y encontré el comando python trace, pero solo muestra un montón de actividad en las principales bibliotecas de Python.¿Cómo puedo rastrear las importaciones de Python?

básicamente estoy buscando una aplicación que me va a mostrar algo como:

App1 >>imports>> App2,App3.method 
App2 >>imports>> App3,etc 

tan sólo pudiera mirar a través de todos mis archivos, pero prefiero no, es una gran aplicación.

Respuesta

11

Se puede usar uno de estos scripts para hacer gráficos de dependencia módulo de Python:

+1

Snakefood terminó siendo lo que yo quería. Sin embargo, lleva un poco de esfuerzo hacer que funcione para una mayor cantidad de archivos. – Jeff

+0

@Jeff: Sí, requiere un poco de esfuerzo configurar y leer la documentación. ¡Me alegro de que pudieras hacerlo funcionar! – unutbu

-2

No debería ser posible obtener una importación cíclica en python porque comprueba si el módulo ya se ha importado antes de importarlo de nuevo. Solo puede importar un módulo una vez, sin importar cuántas veces llame a importar.

De http://groups.google.com/group/comp.lang.python/browse_thread/thread/1d80a1c6db2b867c?pli=1:

Las importaciones son bastante sencillo realmente. Solo recuerde lo siguiente:

'import' y 'de xxx import yyy' son sentencias ejecutables. Ejecutan cuando el programa en ejecución alcanza esa línea .

Si un módulo no está en sys.modules, entonces una importación crea la nueva entrada de módulo en sys.modules y después ejecuta el código en el módulo. No devuelve el control al módulo de llamada hasta que se completa la ejecución.

Si un módulo no existe en sys.modules entonces una importación simplemente devuelve que módulo de si es o no se ha completado la ejecución de . Esa es la razón por la cual las importaciones cíclicas pueden devolver los módulos que parecen estar parcialmente vacíos.

Por último, la ejecución de la secuencia de comandos se ejecuta en un módulo denominado __main__, importando el guión bajo su propio nombre va a crear un nuevo módulo no relacionado con __main__.

Coja ese lote y usted no debe sorprenderse cuando importan módulos.

+6

Es muy posible conseguir importaciones cíclicos. No darán vueltas infinitamente, pero pueden crear problemas donde una función no se define cuando es necesario porque dos archivos se importan entre sí. –

+3

Las importaciones cíclicas en python son solo un problema cuando se importa un ítem desde un módulo, y el otro módulo lo importa. Si hace esto: En A.py: Importar B En B.py: Importar A Entonces no tendrá un problema aunque se importen cíclicamente entre sí, porque las referencias se difieren a la ejecución/uso real de la importación artículos. Solo cuando solicita un elemento de otro módulo (es decir, solicita una referencia en el momento de la importación) que aún no se ha definido, causa problemas. –

9

Intente utilizar python -v para ejecutar su programa. Trazará la secuencia de las importaciones.

Otra opción es pylint, que le avisará de todo tipo de problemas, incluidas las importaciones cíclicas.

+3

Quería usar esta opción -v mientras ejecuto python bajo uwsgi. Terminé agregando esto a mi archivo uwsgi ini: 'env = PYTHONVERBOSE = 1' Y la salida entra en lo que se especifica en el archivo de registro uwsgi normal. –

14

Aquí hay una forma sencilla (y un poco rudimentaria ;-) rastrear "que está tratando de importar lo que" en términos de nombres de los módulos:

import inspect 
import __builtin__ 
savimp = __builtin__.__import__ 

def newimp(name, *x): 
    caller = inspect.currentframe().f_back 
    print name, caller.f_globals.get('__name__') 
    return savimp(name, *x) 

__builtin__.__import__ = newimp 

que da, por ejemplo (después de haber guardado esto como tracimp.py):

$ python -c 'import tracimp; import email; import sys; import email.mime' 
email __main__ 
sys email 
email.mime email 
sys __main__ 
email.mime __main__ 

Como ve, una característica específica de "ajustar" el __import__ incorporado es que no se silenciará por el hecho de que un módulo que se está importando ya está en sys.modules: ya que ocuparse de eso es uno de los trabajos de __import__ , se llama a nuestro contenedor para que ambos módulos "se carguen por primera vez" y que solo van a obtenerse desde sys.modules porque ya se importaron anteriormente. Esto debería ser muy útil cuando intente diagnosticar importaciones circulares (se reduce a encontrar bucles en el gráfico dirigido cuyos bordes están identificados por los dos nombres de módulo, importados e importadores, que este enfoque simple está imprimiendo en cada línea de salida).

Cuestiones relacionadas