Ouvrir le fichier dans un emplacement relatif en Python

133

Supposons que le code python soit exécuté dans un répertoire Windows inconnu, disons «main», et partout où le code est installé lorsqu'il s'exécute, il doit accéder au répertoire «main / 2091 / data.txt».

comment utiliser la fonction open (location)? quel devrait être l'emplacement?

Éditer :

J'ai trouvé que le code simple ci-dessous fonctionnera..a-t-il des inconvénients?

    file="\2091\sample.txt"
    path=os.getcwd()+file
    fp=open(path,'r+');
Camélia
la source
1
Vous utilisez des barres obliques inverses sans échappement. C'est un inconvénient.
orip
6
Plusieurs inconvénients. 1) Comme pour @orip, utilisez des barres obliques pour les chemins, même sous Windows. Votre chaîne ne fonctionnera pas. Ou utilisez des chaînes brutes comme r"\2091\sample.txt". Ou leur échapper comme "\\2091\\sample.txt"(mais c'est ennuyeux). En outre, 2) vous utilisez getcwd () qui est le chemin dans lequel vous vous trouviez lorsque vous exécutez le script. Je pensais que vous vouliez par rapport à l'emplacement du script (mais je me demande maintenant). Et 3), utilisez toujours des os.pathfonctions pour manipuler les chemins. Votre ligne de jonction de chemin doit être os.path.join(os.getcwd(), file)4) le; est inutile
Russ
3
Et pour faire bonne mesure ... 5) agents de contexte d'utilisation pour le garder propre et éviter d' oublier de fermer votre fichier: with open(path, 'r+') as fp:. Voir ici pour la meilleure explication des withdéclarations que j'ai vues.
Russ
à côté du soin nécessaire sur les barres obliques, comme il vient d'être indiqué, il y a la fonction os.path.abspathpour obtenir facilement le chemin complet du chemin relatif à ouvrir. la déclaration finale ressemble à ceci:os.path.abspath('./2091/sample.txt')
OPMendeavour

Réponses:

189

Avec ce type de chose, vous devez faire attention à votre répertoire de travail réel. Par exemple, vous ne pouvez pas exécuter le script à partir du répertoire dans lequel se trouve le fichier. Dans ce cas, vous ne pouvez pas simplement utiliser un chemin relatif par lui-même.

Si vous êtes sûr que le fichier souhaité se trouve dans un sous-répertoire sous l'endroit où se trouve réellement le script, vous pouvez l'utiliser __file__pour vous aider ici. __file__est le chemin d'accès complet à l'emplacement du script que vous exécutez.

Vous pouvez donc jouer avec quelque chose comme ça:

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
la source
J'ai trouvé que le code simple ci-dessous fonctionnera..a-t-il des inconvénients? <pre> file = "\ sample.txt" path = os.getcwd () + str (loc) + file fp = open (path, 'r +'); <code>
@Arash L'inconvénient est que le cwd (répertoire de travail actuel) peut être n'importe quoi, et ne sera pas nécessairement là où se trouve votre script.
Cory Mawhorter
5
__file__est un chemin relatif (au moins sur ma configuration, pour une raison quelconque), et vous devez d' os.path.abspath(__file__)abord appeler . osx / homebrew 2.7
Cory Mawhorter
2
os.path.dirname ( fichier ) ne fonctionne pas pour moi dans Python 2.7. Il est NameError: name '__file__' is not defined
diffusé
1
@Soumendra Je pense que vous l'essayez dans la console. Essayez-le dans un fichier * .py.
Enku
35

Ce code fonctionne très 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
la source
Pour moi, l'accès au fichier dans le dossier parent du dossier actuel n'a pas fonctionné..le .. est ajouté sous forme de chaîne ..
M. Paul
N'a pas fonctionné sous Windows. Le chemin d'accès au fichier est correct mais Python indique «fichier introuvable» et affiche le chemin avec des séparateurs \\.
lonstar
26

J'ai créé un compte juste pour pouvoir clarifier une divergence que je pense avoir trouvée dans la réponse originale de Russ.

Pour référence, sa réponse initiale était:

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

C'est une excellente réponse car elle tente de créer dynamiquement un chemin système absolu vers le fichier souhaité.

Cory Mawhorter a remarqué qu'il s'agissait d' __file__un chemin relatif (c'est aussi le cas sur mon système) et a suggéré d'utiliser os.path.abspath(__file__). os.path.abspath, cependant, renvoie le chemin absolu de votre script actuel (ie /path/to/dir/foobar.py)

Pour utiliser cette méthode (et comment je l'ai finalement fait fonctionner), vous devez supprimer le nom du script à la fin du chemin:

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)

Le abs_file_path résultant (dans cet exemple) devient: /path/to/dir/2091/data.txt

Grant Hulegaard
la source
14
Vous pouvez même combiner les deux approches pour la plus simpleos.path.dirname(os.path.abspath(__file__))
Luke Taylor
1
@LukeTaylor En effet, ce serait mieux que d'essayer de reproduire la os.path.dirnamefonctionnalité vous-même comme je l'ai fait dans ma réponse l'année dernière.
Grant Hulegaard
19

Cela dépend du système d'exploitation que vous utilisez. Si vous voulez une solution compatible avec Windows et * nix, quelque chose comme:

from os import path

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

devrait bien fonctionner.

Le pathmodule est capable de formater un chemin pour n'importe quel système d'exploitation sur lequel il s'exécute. De plus, python gère très bien les chemins relatifs, tant que vous disposez des autorisations appropriées.

Modifier :

Comme mentionné par kindall dans les commentaires, python peut de toute façon convertir entre les chemins de style Unix et de style Windows, donc même un code plus simple fonctionnera:

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

Cela étant dit, le pathmodule a encore quelques fonctions utiles.

Wilduck
la source
3
relpath()convertit un chemin en chemin relatif. Comme c'est déjà un chemin relatif, cela ne fera rien.
quelque sorte
Il le convertira d'un chemin de style Unix en chemin de style Windows le cas échéant. Y a-t-il une autre fonction dans le os.pathmodule qui serait un meilleur choix?
Wilduck
1
Windows fonctionnera déjà correctement avec un chemin de style UNIX. Au moins la série basée sur NT sera (2000, XP, Vista, 7). Aucune conversion n'est nécessaire.
kindall
7
Cette réponse n'est pas tout à fait correcte et causera des problèmes. Les chemins relatifs sont par défaut relatifs au répertoire de travail actuel (chemin à partir duquel le script a été exécuté) et NON à l'emplacement réel du script. Vous devez utiliser __file__. S'il vous plaît voir ma réponse.
Russ
L'auteur de cette réponse a-t-il confondu os.path.relpath avec os.path.abspath?
foobaritchen
15

Je passe beaucoup de temps à découvrir pourquoi mon code ne trouve pas mon fichier exécutant Python 3 sur le système Windows. Alors j'ai ajouté. avant / et tout fonctionnait 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
la source
Mieux:file_path = os.path.join(script_dir, 'output03.txt')
Mr_and_Mrs_D
J'ai essayé sur Windows OS mais je n'ai pas eu de succès.
Ângelo Polotto
Intéressant - pouvez-vous imprimer script_dir? Puis tournez-le vers le chemin absolu comme dansscript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D
J'essaierai que, si je réussis, je changerai la réponse.
Ângelo Polotto
6

Code:

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

Explication:

Importer la bibliothèque:

import os

Utilisez __file__pour atteindre le chemin du script actuel:

script_path = os.path.abspath(__file__)

Sépare le chemin du script en plusieurs éléments:

path_list = script_path.split(os.sep)

Supprimez le dernier élément de la liste (le fichier de script réel):

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

Ajoutez le chemin du fichier relatif:

rel_path = "main/2091/data.txt

Rejoignez les éléments de la liste et ajoutez le fichier du chemin relatif:

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

Vous êtes maintenant prêt à faire ce que vous voulez avec le fichier, par exemple:

file = open(path)
Patriotes299
la source
Au lieu de cela, path = "/".join(script_directory) + "/" + rel_pathvous devez utiliser le module os comme dans path = os.path.join(script_directory, rel_path). Au lieu d'analyser manuellement le chemin, vous devriez utiliserscript_path = os.path.dirname(__file__)
Mr_and_Mrs_D
4

Essaye ça:

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 a introduit une nouvelle bibliothèque standard pour traiter les fichiers et les chemins appelée pathlib. Ça marche pour moi!

dcampos
la source
3

Si le fichier est dans votre dossier parent, par exemple. follower.txt, vous pouvez simplement utiliseropen('../follower.txt', 'r').read()

Olivia Liao
la source
2

Je ne sais pas si cela fonctionne partout.

J'utilise ipython dans ubuntu.

Si vous souhaitez lire le fichier dans le sous-répertoire du dossier actuel:

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

votre script est dans le dossier courant, essayez simplement ceci:

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

Python passe simplement le nom de fichier que vous lui donnez au système d'exploitation, qui l'ouvre. Si votre système d'exploitation prend en charge les chemins relatifs comme main/2091/data.txt(indice: c'est le cas), cela fonctionnera bien.

Vous constaterez peut-être que le moyen le plus simple de répondre à une question comme celle-ci est de l'essayer et de voir ce qui se passe.

kindall
la source
2
Ce n'est pas vrai ... le répertoire de travail à l'intérieur d'un script est l'emplacement à partir duquel vous avez exécuté le script, pas l'emplacement du script. Si vous exécutez le script depuis un autre endroit (peut-être que le script se trouve dans votre chemin système), le chemin relatif vers le sous-répertoire ne fonctionnera pas. S'il vous plaît voir ma réponse sur la façon de contourner cela.
Russ
@Russ - l'exemple de l'OP utilise getcwd(). J'ai lu la description originale comme "relative à l'endroit où j'exécute le script, quel que soit l'endroit où se trouve le code".
orip
@orip - l'OP a ajouté l'appel getcwd () 3 heures après la question. Peu importe ... passer à autre chose. :)
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
la source
0

Quand j'étais débutant, j'ai trouvé ces descriptions un peu intimidantes. Comme au début j'essaierais For Windows

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

et cela soulèverait un syntax error. J'avais l'habitude d'être beaucoup confus. Puis après avoir surfé sur google. a trouvé pourquoi l'erreur s'est produite. Écrire ceci pour les débutants

C'est parce que pour que le chemin soit lu en Unicode, vous ajoutez simplement un \lors du démarrage du chemin du fichier

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

Et maintenant cela fonctionne juste ajouter \avant de démarrer le répertoire.

Chidhvilas
la source
1
Les backslashes sont des caractères d'échappement pour plusieurs caractères. Si vous rencontrez \tcomme par exemple \top\directory, que «\ t» est interprété comme un caractère de tabulation et votre «astuce» échoue. La meilleure option est d'utiliser le format de chaîne brute r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'qui n'essaye pas d '«échapper» les caractères.
Ronald le