2009-11-28 6 views
7

tengo algo de código que carga un archivo de configuración por defecto y luego permite que los usuarios proporcionan sus propios archivos de Python como configuración adicional suplementario o anulaciones de los valores por defecto:Python: execfile del directorio de trabajo de otros archivos?

# foo.py 

def load(cfg_path=None): 
    # load default configuration 
    exec(default_config) 

    # load user-specific configuration 
    if cfg_path: 
     execfile(cfg_path) 

Hay un problema, sin embargo: execfile() ejecuta las directivas de el archivo especificado por cfg_path como si estuviera en el directorio de trabajo foo.py, no su propio directorio de trabajo. Por lo tanto, las directivas import pueden fallar si el archivo cfg_path hace, digamos, from m import x donde m es un módulo en el mismo directorio que cfg_path.

¿Cómo hago para execfile() desde el directorio de trabajo de su argumento, o de otra forma alcanzo un resultado equivalente? Además, me dijeron que execfile está en desuso en Python 3 y que debería estar usando exec, así que si hay una forma mejor de hacerlo, soy todo oídos.

Nota: No creo que las soluciones que simplemente cambian el directorio de trabajo sean correctas. Eso no pondrá esos módulos en la ruta de búsqueda de módulos del intérprete, hasta donde yo sé.

Respuesta

7

os.chdir le permite cambiar el directorio de trabajo como lo desee (puede extraer el directorio de trabajo de cfg_path con os.path.dirname); asegúrese de obtener primero el directorio actual con os.getcwd si desea restaurarlo cuando termine de ejecutar cfg_path.

Python 3 no eliminar efectivamente execfile (a favor de una secuencia en la que se lee el archivo, compile los contenidos, a continuación, exec ellos), pero usted no necesita preocuparse de que, si actualmente la codificación en Python 2.6, ya la fuente 2to3 de traducción de fuente a fuente trata todo esto sin problemas y sin problemas.

Editar: el OP dice, en un comentario, que execfile inicia un proceso separado y no respeta el directorio de trabajo actual. Esto es falso, y he aquí un ejemplo que muestra que es:

import os 

def makeascript(where): 
    f = open(where, 'w') 
    f.write('import os\nprint "Dir in file:", os.getcwd()\n') 
    f.close() 

def main(): 
    where = '/tmp/bah.py' 
    makeascript(where) 
    execfile(where) 
    os.chdir('/tmp') 
    execfile(where) 

if __name__ == '__main__': 
    main() 

La ejecución de este en mi máquina produce una salida como:

Dir in file: /Users/aleax/stko 
Dir in file: /private/tmp 

mostrando claramente que execfilehace seguir usando el directorio de trabajo que es establecido en el momento en que se ejecuta execfile. (Si el archivo ejecutado cambia el directorio de trabajo, eso se reflejará después de execfile devuelve - ¡exactamente porque todo es teniendo lugar en el mismo proceso!).

Por lo tanto, cualquier problema que el OP todavía está observando son no atada al directorio de trabajo actual (es difícil de diagnosticar lo que realmente pueden ser, sin ver el código y los detalles exactos de los problemas observados ;-).

+0

Gracias por la respuesta. Desafortunadamente, esto no parece funcionar para mí. 'execfile()' parece estar iniciando un proceso completamente nuevo con su propio directorio de trabajo, que no es el mismo que el que estoy iniciando. –

+0

No, @Kyle, 'execfile' no inicia un proceso por separado, y ** respeta ** el directorio de trabajo actual. Editando mi respuesta para mostrar un ejemplo simple que demuestre que estás equivocado. –

Cuestiones relacionadas