Les chemins relatifs en Python

je suis en train de construire un script d'aide simple pour le travail qui va copier quelques fichiers de template dans notre base de code dans le répertoire courant. Je n'ai pas, cependant, le chemin absolu vers le répertoire où les gabarits sont stockés. J'ai un chemin relatif à partir du script mais quand j'ai appeler le script, il le considère comme un chemin relatif au répertoire de travail courant. Y a-t-il un moyen de spécifier que cette url relative provient de l'emplacement du script?

161
demandé sur baudtack 2009-05-28 01:43:21

12 réponses

Dans le fichier de script, vous voulez faire quelque chose comme ceci:

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

cela vous donnera le chemin absolu vers le fichier que vous recherchez. Notez que si vous utilisez setuptools, vous devriez probablement utiliser son package resources API à la place.

UPDATE : je réponds à un commentaire ici pour pouvoir coller un échantillon de code. :- )

Am Je me trompe en pensant que __file__ n'est pas toujours disponible (par exemple quand vous exécutez le fichier directement plutôt que de l'importer)?

je suppose que vous voulez dire le script __main__ quand vous mentionnez l'exécution directe du fichier. Si c'est le cas, cela ne semble pas être le cas sur mon système (python 2.5.1 sur OS X 10.5.7):

#foo.py
import os
print os.getcwd()
print __file__

#in the interactive interpreter
>>> import foo
/Users/jason
foo.py

#and finally, at the shell:
~ % python foo.py
/Users/jason
foo.py

cependant, je sais qu'il y a quelques bizarreries avec __file__ sur les extensions C. Par exemple, je peux le faire ceci sur mon Mac:

>>> import collections #note that collections is a C extension in Python 2.5
>>> collections.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-
dynload/collections.so'

cependant, cela soulève une exception sur ma machine Windows.

203
répondu Jason Baker 2018-05-12 18:54:57

vous avez besoin de os.path.realpath (exemple ci-dessous ajoute le répertoire parent à votre chemin)

import sys,os
sys.path.append(os.path.realpath('..'))
52
répondu user989762 2012-03-19 10:24:27

comme indiqué dans la réponse acceptée

import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, '/relative/path/to/file/you/want')

je veux juste ajouter que

cette dernière chaîne ne peut pas commencer avec le backslash, infact aucune chaîne devrait inclure un antislash

ça devrait être quelque chose comme

import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, 'relative','path','to','file','you','want')

la réponse acceptée peut être trompeuse dans certains cas , veuillez vous référer à this lien pour plus de détails

35
répondu Ahmed 2017-05-23 11:47:26

considérez mon code:

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)
11
répondu Fahad Haleem 2015-10-06 15:17:35

voir sys.chemin Comme initialisé au démarrage du programme, le premier élément de cette liste, chemin[0], est le répertoire contenant le script qui a été utilisé pour invoquer l'interpréteur Python.

utilisez ce chemin comme dossier racine à partir duquel vous appliquez votre chemin relatif

>>> import sys
>>> import os.path
>>> sys.path[0]
'C:\Python25\Lib\idlelib'
>>> os.path.relpath(sys.path[0], "path_to_libs") # if you have python 2.6
>>> os.path.join(sys.path[0], "path_to_libs")
'C:\Python25\Lib\idlelib\path_to_libs'
10
répondu Tom Leys 2009-05-27 21:47:16

au lieu d'utiliser

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

comme dans la réponse acceptée, il serait plus robuste à utiliser:

import inspect
import os
dirname = os.path.dirname(os.path.abspath(inspect.stack()[0][1]))
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

parce que l'utilisation de __file__ va retourner le fichier à partir duquel le module a été chargé, s'il a été chargé à partir d'un fichier, donc si le fichier avec le script est appelé d'ailleurs, le répertoire retourné ne sera pas correct.

ces réponses donnent plus de détails: https://stackoverflow.com/a/31867043/5542253 et https://stackoverflow.com/a/50502/5542253

5
répondu smiley 2018-05-12 18:59:05

ce code renvoie le chemin absolu au script principal.

import os
def whereAmI():
    return os.path.dirname(os.path.realpath(__import__("__main__").__file__))

cela fonctionnera même dans un module.

4
répondu BookOwl 2016-03-24 20:03:52

c'est 2018 maintenant, et Python ont déjà évolué vers le __future__ il y a longtemps. Alors que diriez-vous d'utiliser l'incroyable pathlib venir avec Python 3.4 pour accomplir la tâche au lieu de lutter avec os , os.path , glob , shutil , etc.

nous avons donc ici 3 chemins (éventuellement dupliqués):

  • mod_path : qui est le chemin du simple helper script
  • src_path : qui contient un couple de fichiers de modèle en attente d'être copié.
  • cwd : répertoire courant , la destination de ces fichiers de template.

et le problème est: nous n'avons pas de le chemin d'accès complet de src_path , seulement savoir chemin relatif à la mod_path .

maintenant, résolvons cela avec le The amazing pathlib :

# Hope you don't be imprisoned by legacy Python code :)
from pathlib import Path

# `cwd`: current directory is straightforward
cwd = Path.cwd()

# `mod_path`: According to the accepted answer and combine with future power
# if we are in the `helper_script.py`
mod_path = Path(__file__).parent
# OR if we are `import helper_script`
mod_path = Path(helper_script.__file__).parent

# `src_path`: with the future power, it's just so straightforward
relative_path_1 = 'same/parent/with/helper/script/'
relative_path_2 = '../../or/any/level/up/'
src_path_1 = (mod_path / relative_path_1).resolve()
src_path_2 = (mod_path / relative_path_2).resolve()

dans le futur, c'est aussi simple que ça. : D


de plus, nous pouvons sélectionner et vérifier et copier/déplacer ces fichiers de modèles avec pathlib :

if src_path != cwd:
    # When we have different types of files in the `src_path`
    for template_path in src_path.glob('*.ini'):
        fname = template_path.name
        target = cwd / fname
        if not target.exists():
            # This is the COPY action
            with target.open(mode='wb') as fd:
                fd.write(template_path.read_bytes())
            # If we want MOVE action, we could use:
            # template_path.replace(target)
4
répondu YaOzI 2018-07-03 07:40:46

Bonjour tout d'abord vous devez comprendre les fonctions os.chemin.abspath (chemin) et os.chemin.relpath(chemin de)

en abrégé os.chemin.abspath(chemin de) fait un chemin relatif à chemin absolu . Et si le chemin fourni est lui-même un chemin absolu, alors la fonction renvoie le même chemin.

de même OS.chemin.relpath(chemin de) fait un chemin absolu à chemin relatif . Et si le chemin fourni est lui-même un chemin d'accès relatif alors la fonction renvoie le même chemin.

l'exemple ci-dessous peut vous permettre de comprendre le concept ci-dessus correctement :

supposons que j'ai un fichier input_file_list.txt qui contient la liste des fichiers être traité par mon script python.

D:\conc\input1.dic

D:\conc\input2.dic

D:\Copyioconc\input_file_list.txt

si vous voyez la structure du dossier ci-dessus, input_file_list.txt est présent dans le dossier Copyofconc et les fichiers à traiter par le script python sont présents dans le dossier conc folder

mais le contenu du fichier input_file_list.txt est comme suit:

..\conc\input1.dic

..\conc\input2.dic

Et mon script python est présent dans D: .

et le chemin relatif fourni dans la input_file_list.txt sont relatifs au chemin de input_file_list.txt fichier.

Ainsi, lorsque le script python exécutera le répertoire de travail courant (utilisez os.getcwd () pour obtenir le chemin)

comme mon chemin relatif est relatif à input_file_list.txt , c'est-à-dire "D:\Copyofconc " , je dois changer le répertoire courant de travail en "D:\Copyofconc " .

donc je dois utiliser os.chdir("D:\Copyofconc') , ainsi le courant le répertoire de travail doit être "D:\Copyofconc " .

maintenant pour obtenir les fichiers entrée.dic et input2.dic , je vais lire les lignes "..\conc\input1.dic" puis utilisez la commande

input1_path= os.chemin.abspath ('..\conc\input1.dic') (pour modifier le chemin d'accès relatif au chemin d'accès absolu. Ici comme répertoire de travail actuel est "D:\Copyofconc", le fichier ".\conc\input1.DIC" doit être accessible par rapport à "D:\Copyofconc")

donc input1_path doit être "D:\conc\input1.dic "

3
répondu Chandrajyoti Das 2013-12-07 04:30:00

une alternative qui fonctionne pour moi:

this_dir = os.path.dirname(__file__) 
filename = os.path.realpath("{0}/relative/file.path".format(this_dir))
2
répondu J0hnG4lt 2014-10-10 09:19:19

ce qui a fonctionné pour moi c'est d'utiliser sys.path.insert . Puis j'ai spécifié le répertoire que j'avais besoin d'aller. Par exemple, j'avais juste besoin d'aller dans un répertoire.

import sys
sys.path.insert(0, '../')
1
répondu Whitecat 2017-03-16 18:14:35

Je ne suis pas sûr que cela s'applique à certaines des anciennes versions, mais je crois que Python 3.3 a le support natif relatif path.

par exemple, le code suivant devrait créer un fichier texte dans le même dossier que le script python:

open("text_file_name.txt", "w+t")

(notez qu'il ne devrait pas y avoir de barre oblique avant ou arrière au début si c'est un chemin relatif)

-2
répondu Samy Bencherif 2014-06-04 14:41:21