web-dev-qa-db-fra.com

Pourquoi os.path.join () ne fonctionne-t-il pas dans ce cas?

Le code ci-dessous ne se joindra pas. Lors du débogage, la commande ne stocke pas le chemin complet, mais uniquement la dernière entrée.

os.path.join('/home/build/test/sandboxes/', todaystr, '/new_sandbox/')

Lorsque je teste cela, il ne stocke que la partie /new_sandbox/ du code.

293
chrissygormley

Les dernières chaînes ne doivent pas commencer par une barre oblique. S'ils commencent par une barre oblique, ils sont alors considérés comme un "chemin absolu" et tout ce qui les précède est ignoré.

Citant le docs Python pour os.path.join :

Si un composant est un chemin absolu, tous les composants précédents sont supprimés et la jointure continue à partir du composant de chemin absolu.

Remarque sur Windows, le comportement vis-à-vis des lettres de lecteur, qui semble avoir changé par rapport aux versions précédentes Python:

Sous Windows, la lettre de lecteur n'est pas réinitialisée lorsqu'un composant de chemin absolu (par exemple, r'\foo') est rencontré. Si un composant contient une lettre de lecteur, tous les composants précédents sont jetés et la lettre de lecteur est réinitialisée. Notez que puisqu'il existe un répertoire en cours pour chaque lecteur, os.path.join("c:", "foo") représente un chemin relatif au répertoire en cours sur le lecteur C: (c:foo), pas c:\foo.

389
Craig McQueen

L'idée de os.path.join() est de rendre votre programme multi-plateforme (linux/windows/etc).

Même une barre oblique le ruine.

Cela n'a donc de sens que d'utiliser un point de référence tel que os.environ['HOME'] ou os.path.dirname(__file__).

144
Antony Hatchkins

os.path.join() peut être utilisé avec os.path.sep pour créer un chemin absolu plutôt que relatif.

os.path.join(os.path.sep, 'home','build','test','sandboxes',todaystr,'new_sandbox')
66
ghammond

N'utilisez pas de barres obliques au début des composants de chemin, sauf lorsque vous vous référez au répertoire racine:

os.path.join('/home/build/test/sandboxes', todaystr, 'new_sandbox')

voir aussi: http://docs.python.org/library/os.path.html#os.path.join

21
miku

Pour aider à comprendre pourquoi ce comportement surprenant n'est pas entièrement terrible, considérons une application qui accepte un nom de fichier de configuration comme argument:

config_root = "/etc/myapp.conf/"
file_name = os.path.join(config_root, sys.argv[1])

Si l'application est exécutée avec:

$ myapp foo.conf

Le fichier de configuration /etc/myapp.conf/foo.conf sera utilisé.

Mais considérons ce qui se passe si l'application est appelée avec:

$ myapp /some/path/bar.conf

Ensuite, myappdevrait utiliser le fichier de configuration sous /some/path/bar.conf (et non /etc/myapp.conf/some/path/bar.conf ou similaire).

Ce n'est peut-être pas génial, mais je crois que c'est la motivation pour le comportement absolu sur le chemin.

17
David Wolever

C'est parce que votre '/new_sandbox/' commence par un / et est donc supposé être relatif au répertoire racine. Supprimez le / initial.

11
Amber

Pour rendre votre fonction plus portable, utilisez-la comme telle:

os.path.join(os.sep, 'home', 'build', 'test', 'sandboxes', todaystr, 'new_sandbox')

ou

os.path.join(os.environ.get("HOME"), 'test', 'sandboxes', todaystr, 'new_sandbox')
8
NuclearPeon

Essayez la combinaison de split("/") et * pour les chaînes avec des jointures existantes.

import os

home = '/home/build/test/sandboxes/'
todaystr = '042118'
new = '/new_sandbox/'

os.path.join(*home.split("/"), todaystr, *new.split("/"))


Comment ça marche ...

split("/") transforme le chemin existant en liste: ['', 'home', 'build', 'test', 'sandboxes', '']

* devant la liste divise chaque élément de la liste avec son propre paramètre

6
openwonk

Essayez avec new_sandbox seulement

os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox')
3
YOU

faites-le comme ça, sans trop les barres obliques

root="/home"
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox")
2
ghostdog74

Notez qu'un problème similaire peut vous piquer si vous utilisez os.path.join() pour inclure une extension qui inclut déjà un point, ce qui se produit automatiquement lorsque vous utilisez os.path.splitext(). Dans cet exemple:

components = os.path.splitext(filename)
prefix = components[0]
extension = components[1]
return os.path.join("avatars", instance.username, prefix, extension)

Même si extension peut être .jpg, vous vous retrouvez avec un dossier nommé "foobar" plutôt qu'un fichier appelé "foobar.jpg". Pour éviter cela, vous devez ajouter l'extension séparément:

return os.path.join("avatars", instance.username, prefix) + extension
0
shacker