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.
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 lecteurC:
(c:foo
), pasc:\foo
.
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__)
.
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')
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
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, myapp
devrait 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.
C'est parce que votre '/new_sandbox/'
commence par un /
et est donc supposé être relatif au répertoire racine. Supprimez le /
initial.
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')
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
Essayez avec new_sandbox
seulement
os.path.join('/home/build/test/sandboxes/', todaystr, 'new_sandbox')
faites-le comme ça, sans trop les barres obliques
root="/home"
os.path.join(root,"build","test","sandboxes",todaystr,"new_sandbox")
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