Abrir archivo en una ubicación relativa en Python

133

Supongamos que el código de Python se ejecuta en un directorio de Windows anterior no conocido como 'main', y donde sea que se instale el código cuando se ejecuta, necesita acceder al directorio 'main / 2091 / data.txt'.

¿Cómo debo usar la función de abrir (ubicación)? ¿Cuál debería ser la ubicación?

Editar:

Descubrí que el siguiente código simple funcionará ... ¿tiene alguna desventaja?

    file="\2091\sample.txt"
    path=os.getcwd()+file
    fp=open(path,'r+');
Camelia
fuente
1
Estás utilizando barras invertidas sin escape. Esa es una desventaja.
orip
66
Varias desventajas. 1) Según @orip, utilice barras diagonales para las rutas, incluso en ventanas. Tu cuerda no funcionará. O use cadenas crudas como r"\2091\sample.txt". O escapar de ellos como "\\2091\\sample.txt"(pero eso es molesto). Además, 2) está utilizando getcwd (), que es la ruta en la que se encontraba cuando ejecutaba el script. Pensé que querías en relación con la ubicación del script (pero ahora me pregunto). Y 3), siempre use os.pathfunciones para manipular rutas. Su línea de unión de ruta debe ser os.path.join(os.getcwd(), file)4) la; no tiene sentido
Russ
3
Y por si acaso ...) 5 guardias uso del contexto para mantenerlo limpio y evitar el olvido de cerrar el archivo: with open(path, 'r+') as fp:. Vea aquí la mejor explicación de las withdeclaraciones que he visto.
Russ
Además del cuidado necesario en las barras, como se acaba de indicar, existe la función os.path.abspathde obtener fácilmente la ruta completa de la ruta relativa para abrir. la declaración final se ve así:os.path.abspath('./2091/sample.txt')
OPMendeavor

Respuestas:

189

Con este tipo de cosas, debe tener cuidado con su directorio de trabajo real. Por ejemplo, no puede ejecutar el script desde el directorio en el que se encuentra el archivo. En este caso, no puede usar una ruta relativa por sí mismo.

Si está seguro de que el archivo que desea está en un subdirectorio debajo de donde se encuentra realmente el script, puede usarlo __file__para ayudarlo aquí. __file__es la ruta completa a donde se encuentra el script que está ejecutando.

Entonces puedes jugar con algo como esto:

import os
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)
Russ
fuente
Descubrí que el siguiente código simple funcionará ... ¿tiene alguna desventaja? <pre> file = "\ sample.txt" path = os.getcwd () + str (loc) + file fp = open (path, 'r +'); <code>
@Arash La desventaja de esto es que el cwd (directorio de trabajo actual) puede ser cualquier cosa, y no necesariamente estará donde se encuentra su script.
Cory Mawhorter
55
__file__es una ruta relativa (al menos en mi configuración, por alguna razón), y debe llamar os.path.abspath(__file__)primero. osx / homebrew 2.7
Cory Mawhorter
2
os.path.dirname ( archivo ) no me funciona en Python 2.7. Está mostrandoNameError: name '__file__' is not defined
Soumendra
1
@Soumendra Creo que lo estás intentando en la consola. Pruébelo en un archivo * .py.
Enku
35

Este código funciona bien:

import os


def readFile(filename):
    filehandle = open(filename)
    print filehandle.read()
    filehandle.close()



fileDir = os.path.dirname(os.path.realpath('__file__'))
print fileDir

#For accessing the file in the same folder
filename = "same.txt"
readFile(filename)

#For accessing the file in a folder contained in the current folder
filename = os.path.join(fileDir, 'Folder1.1/same.txt')
readFile(filename)

#For accessing the file in the parent folder of the current folder
filename = os.path.join(fileDir, '../same.txt')
readFile(filename)

#For accessing the file inside a sibling folder.
filename = os.path.join(fileDir, '../Folder2/same.txt')
filename = os.path.abspath(os.path.realpath(filename))
print filename
readFile(filename)
Fahad Haleem
fuente
Para mí, el acceso al archivo en la carpeta principal de la carpeta actual no funcionó ... el ... se agrega como una cadena ...
M. Paul
No funcionó en Windows. La ruta al archivo es correcta, pero Python indica "archivo no encontrado" y muestra la ruta con \\ separadores.
lonstar
26

Creé una cuenta solo para poder aclarar una discrepancia que creo que encontré en la respuesta original de Russ.

Como referencia, su respuesta original fue:

import os
script_dir = os.path.dirname(__file__)
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

Esta es una gran respuesta porque está tratando de crear dinámicamente una ruta absoluta del sistema al archivo deseado.

Cory Mawhorter notó que __file__es un camino relativo (también lo está en mi sistema) y sugirió usarlo os.path.abspath(__file__). os.path.abspath, sin embargo, devuelve la ruta absoluta de su script actual (es decir /path/to/dir/foobar.py)

Para usar este método (y cómo finalmente lo hice funcionar) debe eliminar el nombre del script al final de la ruta:

import os
script_path = os.path.abspath(__file__) # i.e. /path/to/dir/foobar.py
script_dir = os.path.split(script_path)[0] #i.e. /path/to/dir/
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

El abs_file_path resultante (en este ejemplo) se convierte en: /path/to/dir/2091/data.txt

Grant Hulegaard
fuente
14
Incluso podría combinar ambos enfoques para el más simpleos.path.dirname(os.path.abspath(__file__))
Luke Taylor
1
@LukeTaylor De hecho, eso sería mejor que intentar replicar la os.path.dirnamefuncionalidad usted mismo como lo hice en mi respuesta el año pasado.
Grant Hulegaard
19

Depende de qué sistema operativo estés usando. Si desea una solución que sea compatible con Windows y * nix, algo como:

from os import path

file_path = path.relpath("2091/data.txt")
with open(file_path) as f:
    <do stuff>

Debería funcionar bien.

El pathmódulo puede formatear una ruta para cualquier sistema operativo en el que se esté ejecutando. Además, python maneja las rutas relativas muy bien, siempre que tenga los permisos correctos.

Editar :

Como mencionó kindall en los comentarios, python puede convertir entre rutas de estilo unix y ventanas de todos modos, por lo que incluso un código más simple funcionará:

with open("2091/data/txt") as f:
    <do stuff>

Dicho esto, el pathmódulo todavía tiene algunas funciones útiles.

Wilduck
fuente
3
relpath()convierte un nombre de ruta en una ruta relativa. Como ya es un camino relativo, no hará nada.
poco el
Lo convertirá de una ruta de estilo unix a una ruta de estilo de Windows, si corresponde. ¿Hay otra función en el os.pathmódulo que sería una mejor opción?
Wilduck
1
Windows ya funcionará bien con una ruta de estilo UNIX. Al menos la serie basada en NT lo hará (2000, XP, Vista, 7). No es necesaria la conversión.
poco el
77
Esta respuesta no es del todo correcta y causará problemas. Las rutas relativas son por defecto relativas al directorio de trabajo actual (ruta desde la que se ejecutó el script), y NO a la ubicación real del script. Necesitas usar __file__. Por favor mira mi respuesta.
Russ
¿Confundió el autor de esta respuesta os.path.relpath con os.path.abspath?
foobarbecue
15

Paso mucho tiempo descubriendo por qué mi código no pudo encontrar mi archivo que ejecuta Python 3 en el sistema Windows. Entonces agregué. antes / y todo funcionó bien:

import os

script_dir = os.path.dirname(__file__)
file_path = os.path.join(script_dir, './output03.txt')
print(file_path)
fptr = open(file_path, 'w')
Ângelo Polotto
fuente
Mejor:file_path = os.path.join(script_dir, 'output03.txt')
Mr_and_Mrs_D
Lo intenté en el sistema operativo Windows pero no tuve éxito.
Ângelo Polotto
Interesante: ¿puedes imprimir script_dir? Luego gírelo a la ruta absoluta como enscript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D
Intentaré eso, si tengo éxito, cambiaré la respuesta.
Ângelo Polotto
6

Código:

import os
script_path = os.path.abspath(__file__) 
path_list = script_path.split(os.sep)
script_directory = path_list[0:len(path_list)-1]
rel_path = "main/2091/data.txt"
path = "/".join(script_directory) + "/" + rel_path

Explicación:

Biblioteca de importación:

import os

Use __file__para obtener la ruta actual del script:

script_path = os.path.abspath(__file__)

Separa la ruta del script en varios elementos:

path_list = script_path.split(os.sep)

Elimine el último elemento de la lista (el archivo de script real):

script_directory = path_list[0:len(path_list)-1]

Agregue la ruta del archivo relativo:

rel_path = "main/2091/data.txt

Únase a los elementos de la lista y agregue el archivo de la ruta relativa:

path = "/".join(script_directory) + "/" + rel_path

Ahora está configurado para hacer lo que quiera con el archivo, como, por ejemplo:

file = open(path)
Patriots299
fuente
En lugar de path = "/".join(script_directory) + "/" + rel_pathusar el módulo os como en path = os.path.join(script_directory, rel_path). En lugar de analizar manualmente la ruta que debería usarscript_path = os.path.dirname(__file__)
Mr_and_Mrs_D
4

Prueba esto:

from pathlib import Path

data_folder = Path("/relative/path")
file_to_open = data_folder / "file.pdf"

f = open(file_to_open)

print(f.read())

Python 3.4 introdujo una nueva biblioteca estándar para manejar archivos y rutas llamada pathlib. ¡Esto funciona para mi!

dcampos
fuente
3

Si el archivo está en su carpeta principal, por ejemplo. follower.txt, simplemente puede usaropen('../follower.txt', 'r').read()

Olivia Liao
fuente
2

No estoy seguro si esto funciona en todas partes.

Estoy usando ipython en ubuntu.

Si desea leer el archivo en el subdirectorio de la carpeta actual:

/current-folder/sub-directory/data.csv

su script está en la carpeta actual simplemente intente esto:

import pandas as pd
path = './sub-directory/data.csv'
pd.read_csv(path)
Survi
fuente
1

Python solo pasa el nombre de archivo que le das al sistema operativo, que lo abre. Si su sistema operativo admite rutas relativas como main/2091/data.txt(pista: lo hace), entonces eso funcionará bien.

Puede encontrar que la forma más fácil de responder una pregunta como esta es probarla y ver qué sucede.

un poco
fuente
2
No es cierto ... el directorio de trabajo dentro de un script es la ubicación desde la que ejecutó el script, no la ubicación del script. Si ejecuta el script desde otro lugar (tal vez el script está en la ruta del sistema), la ruta relativa al subdirectorio no funcionará. Por favor, vea mi respuesta sobre cómo solucionar esto.
Russ
@Russ: el ejemplo de OP utiliza getcwd(). Leí la descripción original como "en relación con el lugar donde ejecuto el script, independientemente de dónde se encuentre el código".
orip
@orip: el OP agregó la llamada a getcwd () 3 horas después de la pregunta. No importa ... seguir adelante. :)
Russ
1
import os
def file_path(relative_path):
    dir = os.path.dirname(os.path.abspath(__file__))
    split_path = relative_path.split("/")
    new_path = os.path.join(dir, *split_path)
    return new_path

with open(file_path("2091/data.txt"), "w") as f:
    f.write("Powerful you have become.")
Webucator
fuente
0

Cuando era principiante, encontré estas descripciones un poco intimidantes. Como al principio lo intentaría For Windows

f= open('C:\Users\chidu\Desktop\Skipper New\Special_Note.txt','w+')
print(f) 

y esto elevaría un syntax error. Solía ​​confundirme mucho. Luego, después de navegar por google. Encontró por qué ocurrió el error. Escribiendo esto para principiantes

Es porque para que la ruta se lea en Unicode, simplemente agrega un \al iniciar la ruta del archivo

f= open('C:\\Users\chidu\Desktop\Skipper New\Special_Note.txt','w+')
print(f)

Y ahora funciona solo agregue \antes de iniciar el directorio.

Chidhvilas
fuente
1
Las barras invertidas son caracteres de escape para varios personajes. Si te encuentras con, \tpor ejemplo \top\directory, que '\ t' se interpreta como un tabulador y tu 'truco' falla. La mejor opción es utilizar el formato de cadena sin formato r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'que no intenta "escapar" de los caracteres.
Ronald