¿Cómo se determina correctamente el directorio de script actual? [duplicar]
Me gustaría ver cuál es la mejor manera de determinar el directorio de script actual en Python.
Descubrí que, debido a las muchas formas de llamar al código Python, es difícil encontrar una buena solución.
Aquí hay algunos problemas:
__file__
no está definido si el script se ejecuta conexec
,execfile
__module__
está definido sólo en módulos
Casos de uso:
./myfile.py
python myfile.py
./somedir/myfile.py
python somedir/myfile.py
execfile('myfile.py')
(de otro script, que puede estar ubicado en otro directorio y que puede tener otro directorio actual.
Sé que no existe una solución perfecta, pero busco el mejor enfoque que resuelva la mayoría de los casos.
El enfoque más utilizado es os.path.dirname(os.path.abspath(__file__))
, pero esto realmente no funciona si ejecuta el script desde otro con exec()
.
Advertencia
Cualquier solución que utilice el directorio actual fallará; esto puede ser diferente según la forma en que se llama el script o se puede cambiar dentro del script en ejecución.
os.path.dirname(os.path.abspath(__file__))
es de hecho lo mejor que obtendrás.
Es inusual ejecutar un script con exec
/ execfile
; normalmente debería utilizar la infraestructura del módulo para cargar scripts. Si debe utilizar estos métodos, le sugiero configurar __file__
el globals
que pasa al script para que pueda leer ese nombre de archivo.
No hay otra forma de obtener el nombre del archivo en código ejecutado: como notará, el CWD puede estar en un lugar completamente diferente.
Si realmente desea cubrir el caso en el que se llama a un script a través de execfile(...)
, puede usar el inspect
módulo para deducir el nombre del archivo (incluida la ruta). Hasta donde yo sé, esto funcionará para todos los casos que enumeró:
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
En Python 3.4+ puedes usar el pathlib
módulo más simple:
from inspect import currentframe, getframeinfo
from pathlib import Path
filename = getframeinfo(currentframe()).filename
parent = Path(filename).resolve().parent
También puedes usar __file__
(cuando esté disponible) para evitar el inspect
módulo por completo:
from pathlib import Path
parent = Path(__file__).resolve().parent