Solía abrir archivos que estaban en el mismo directorio que el script de Python actualmente en ejecución simplemente usando un comando como
open("Some file.txt", "r")
Sin embargo, descubrí que cuando el script se ejecutaba en Windows haciendo doble clic en él, intentaba abrir el archivo desde el directorio incorrecto.
Desde entonces he usado un comando de la forma
open(os.path.join(sys.path[0], "Some file.txt"), "r")
cada vez que quería abrir un archivo. Esto funciona para mi uso particular, pero no estoy seguro de si sys.path[0]
podría fallar en algún otro caso de uso.
Entonces mi pregunta es: ¿Cuál es la mejor y más confiable forma de abrir un archivo que se encuentra en el mismo directorio que el script Python actualmente en ejecución?
Esto es lo que he podido descubrir hasta ahora:
os.getcwd()
yos.path.abspath('')
devuelve el "directorio de trabajo actual", no el directorio del script.os.path.dirname(sys.argv[0])
yos.path.dirname(__file__)
devuelve la ruta utilizada para llamar al script, que puede ser relativa o incluso en blanco (si el script está en el cwd). Además,__file__
no existe cuando el script se ejecuta en IDLE o PythonWin.sys.path[0]
yos.path.abspath(os.path.dirname(sys.argv[0]))
parece que devuelve el directorio del script. No estoy seguro de si hay alguna diferencia entre estos dos.
Editar:
Me acabo de dar cuenta de que lo que quiero hacer se describirá mejor como "abrir un archivo en el mismo directorio que el módulo contenedor". En otras palabras, si importo un módulo que escribí que está en otro directorio, y ese módulo abre un archivo, quiero que busque el archivo en el directorio del módulo. No creo que nada de lo que he encontrado sea capaz de hacer eso ...
__file__
no se puede usar, use ensys.argv[0]
lugar dedirname(__file__)
. El resto debería funcionar como se esperaba. Me gusta usarlo__file__
porque en el código de la biblioteca, essys.argv[0]
posible que no apunte a su código, especialmente si se importa a través de un script de terceros.realpath( join( getcwd(), dirname(__file__) ))
como se describe aquí?Para citar de la documentación de Python:
sys.path [0] es lo que estás buscando.
fuente
os.path.join(sys.path[0], 'some file.txt')
. Eso debería manejar espacios y barras correctamente en todos los sistemas.Ok esto es lo que hago
sys.argv es siempre lo que escribe en el terminal o utiliza como ruta de archivo al ejecutarlo con python.exe o pythonw.exe
Por ejemplo, puede ejecutar el archivo text.py de varias maneras, cada una de ellas le da una respuesta diferente, siempre le dan la ruta de acceso que escribió Python.
Ok, así que sé que puedes obtener el nombre del archivo, gran cosa, ahora para obtener el directorio de la aplicación puedes saber usar os.path, específicamente abspath y dirname
Eso generará esto:
siempre generará esto sin importar si escribe python test.py o python "C: \ Documents and Settings \ Admin \ test.py"
El problema con el uso de __file__ Considere estos dos archivos test.py
import_test.py
Salida de "python test.py"
Salida de "python test_import.py"
Entonces, como puede ver, el archivo le proporciona siempre el archivo python desde el que se ejecuta, donde sys.argv [0] le proporciona siempre el archivo que ejecutó desde el intérprete. Dependiendo de sus necesidades, tendrá que elegir cuál se adapta mejor a sus necesidades.
fuente
__file__
se supone que "siempre le da la ruta al archivo actual", ysys.argv[0]
se supone que "siempre le da la ruta del script que inició el proceso". En cualquier caso, usar__file__
en el script que se invoca siempre te da resultados precisos.__file__
en el nivel superior del script, funcionará como se esperaba.Pude usar el código proporcionado por dcolish con éxito ya que tenía un problema similar al leer un archivo de texto específico. El archivo no está en el mismo cwd que el archivo Python.
fuente
Lo haría de esta manera:
El código anterior crea una ruta absoluta al archivo usando abspath y es equivalente a usar
normpath(join(os.getcwd(), path))
[eso es de los pydocs]. Luego verifica si ese archivo realmente existe y luego usa un administrador de contexto para abrirlo, de modo que no tenga que acordarse de llamar al cierre en el identificador de archivo. En mi humilde opinión, hacerlo de esta manera te ahorrará mucho dolor a largo plazo.fuente
os.path.abspath
no resuelve las rutas a los archivos en la misma carpeta que el script si el script no está en el directorio actual.