2012-07-28 18 views
11

En algunas de mis aplicaciones Django, estoy usando un archivo settings_local.py para anular las configuraciones que son diferentes en varios entornos (por ejemplo, desarrollo, prueba y producción). Originalmente He utilizado el siguiente código para incluir su contenido en el settings.py:Python: 'import *' vs execfile

try: 
    from settings_local import * 
except ImportError: 
    sys.stderr.write("The settings_local.py file is missing.\n") 
    DEBUG=False 

he encontrado recientemente la función execfile y cambiado a algo como:

try: 
    execfile(path.join(PROJECT_ROOT, "settings_local.py")) 
except IOError: 
    sys.stderr.write("The settings_local.py file is missing.\n" 
    DEBUG=False 

Tanto funciona como es debido, pero me Tengo curiosidad por saber si me falta algún truco y, en general, qué enfoque es más recomendable y por qué.

Respuesta

14

El uso de la función execfile dará como resultado la evaluación del archivo fuente de Python (.py) cada vez que se evalúa el archivo de configuración. Está ejecutando el analizador de Python cada vez. Usar import no necesariamente haría esto (podría usar el archivo .pyc). En general, la primera vez que ejecuta un proyecto en Python (al menos, cPython) se compila en bytecode y no se vuelve a compilar. Estás rompiendo eso. Esto no es necesariamente un problema, pero debes ser consciente de ello.

Usando execfile también dará lugar a todas las importaciones que pueda tener en el archivo settings_local.py siendo re-evaluado en el ámbito de módulo del archivo settings.py. El uso de import * habría incluido todos los artículos en el alcance del módulo settings_local.py. El efecto neto es el mismo (todos los artículos incluidos en el alcance del módulo settings_local.py se incluyen en settings.py) pero el método es diferente.

Finalmente, es normal que los módulos se ejecuten como módulos en lugar de incluidos. Es razonable que el código incluya cosas como os.path.dirname(__file__). Si algún código usara esto, lo confundiría ya que el código ya no se estaría ejecutando en el módulo que el autor razonablemente podría haber esperado. En mi experiencia, las personas usan import no execfile. Django es mucho más "convencional que configuración". Sigue la convención.

+5

'__file__' se puede proporcionar fácilmente a través de argumentos. La principal diferencia es que un módulo se importa exactamente una vez, no importa cuántas veces se ejecute 'import module' (' exec' ejecuta el archivo cada vez que se llama), y 'import' no requiere una ruta explícita al archivo (entonces funcionaría dentro de un archivo zip también). – jfs

+0

@ J.F.Sebastian Esa debería ser una respuesta. – Marcin

+3

Una de las ventajas que encontré sobre execfile (a diferencia de la importación) es que puedo hacerlo de forma dinámica. Específicamente, si tengo una lista de módulos de configuración, puedo hacer un ciclo por la lista, llamando a execfile en cada uno. ¿Hay alguna manera de hacer eso con la importación en su lugar? –

2

La primera versión (from settings_local import *) es lo que todos esperarían ver. También permitirá que los analizadores de código encuentren el módulo.

8

Otra diferencia: execfile obtiene un diccionario de contexto; el contexto global por defecto o un diccionario específico. Esto podría permitir que algunas cosas extrañas

dont_do_this.py:

# Probably not a good thing to do 
z=x+1 # an expression that involves an un-defined field 

Obviamente,

from dont_do_this import * 

falla.

Sin embargo,

d={'x':1} 
execfile('dont_do_this.py', d) 

está bien y los resultados en d=={'x':1, 'z':2}

Tenga en cuenta que

x=1 
execfile('dont_do_this.py') 

está bien y los resultados en la variable z que se añade a las variables globales.