119 votes

Python os.path.join sur Windows

J'essaie d'apprendre le langage python et je crée un programme qui produira un script. Je veux utiliser os.path.join, mais je suis assez confus. D'après le documents si je dis :

os.path.join('c:', 'sourcedir')

J'obtiens "C:sourcedir" . D'après les docteurs, c'est normal, n'est-ce pas ?

Mais lorsque j'utilise la commande copytree, Python l'affiche de la manière souhaitée, par exemple :

import shutil
src = os.path.join('c:', 'src')
dst = os.path.join('c:', 'dst')
shutil.copytree(src, dst)

Voici le code d'erreur que j'obtiens :

WindowsError: \[Error 3\] The system cannot find the path specified: 'C:src/\*.\*'

Si j'enveloppe le os.path.join con os.path.normpath J'obtiens la même erreur.

Si cette os.path.join ne peut pas être utilisé de cette manière, je ne comprends pas très bien sa raison d'être.

D'après les pages proposées par Stack Overflow, les slashs ne doivent pas être utilisés dans les jointures - c'est correct, je suppose ?

0voto

Pratul Points 25

En réponse à votre commentaire : les autres "//" "c :", "c : \\ ' n'a pas fonctionné ( C:\\ a créé deux barres obliques inverses, C:\n'a pas fonctionné du tout)"

Sous Windows, en utilisant os.path.join('c:', 'sourcedir') ajoutera automatiquement deux barres obliques inverses \\ devant sourcedir .

Pour résoudre le problème du chemin d'accès, python fonctionne sous Windows également avec des barres obliques -> '/' il suffit d'ajouter .replace('\\','/') con os.path.join comme suit:-

os.path.join('c:\\', 'sourcedir').replace('\\','/')

par exemple os.path.join('c:\\', 'temp').replace('\\','/')

sortie : C:/temp'

0voto

Vincenzooo Points 899

Les solutions proposées sont intéressantes et offrent une bonne référence, mais elles ne sont que partiellement satisfaisantes. Il est acceptable d'ajouter manuellement le séparateur lorsque vous avez un cas spécifique ou que vous connaissez le format de la chaîne d'entrée, mais il peut y avoir des cas où vous souhaitez le faire de manière programmatique pour des entrées génériques.

Avec un peu d'expérience, je crois que le critère est que le délimiteur de chemin n'est pas ajouté si le premier segment est une lettre de lecteur, c'est-à-dire une lettre unique suivie de deux points, qu'elle corresponde ou non à une unité réelle.

Par exemple :

import os
testval = ['c:','c:\\','d:','j:','jr:','data:']

for t in testval:
    print ('test value: ',t,', join to "folder"',os.path.join(t,'folder'))
test value:  c: , join to "folder" c:folder
test value:  c:\ , join to "folder" c:\folder
test value:  d: , join to "folder" d:folder
test value:  j: , join to "folder" j:folder
test value:  jr: , join to "folder" jr:\folder
test value:  data: , join to "folder" data:\folder

Un moyen pratique de tester les critères et d'appliquer une correction de trajectoire peut être d'utiliser os.path.splitdrive comparer le premier élément renvoyé à la valeur de test, de la manière suivante t+os.path.sep if os.path.splitdrive(t)[0]==t else t .

Test :

for t in testval:
    corrected = t+os.path.sep if os.path.splitdrive(t)[0]==t else t
    print ('original: %s\tcorrected: %s'%(t,corrected),' join corrected->',os.path.join(corrected,'folder'))
original: c:    corrected: c:\  join corrected-> c:\folder
original: c:\   corrected: c:\  join corrected-> c:\folder
original: d:    corrected: d:\  join corrected-> d:\folder
original: j:    corrected: j:\  join corrected-> j:\folder
original: jr:   corrected: jr:  join corrected-> jr:\folder
original: data: corrected: data:  join corrected-> data:\folder

il peut probablement être amélioré pour être plus robuste pour les espaces de fin, et je l'ai testé seulement sur Windows, mais j'espère que cela donne une idée. Voir aussi Os.path : pouvez-vous expliquer ce comportement ? pour des détails intéressants sur les systèmes autres que Windows.

0voto

J'ai contourné ce problème en utilisant :

os.sep.join(list('C:', 'sourcedir'))

join ici n'est pas de os.path.join() mais de ''.join()

Il peut être utile dans la situation suivante :

import os

some_path = r'C:\some_folder\some_file.txt'
path_items = some_path.split(os.sep)
same_path = os.sep.join(path_items)

0voto

vshiro Points 193

Par souci de simplicité, voici une solution de contournement :

my_path = r'D:\test\test2\file.txt' # original path string
drive_letter = my_path.split(':')[0] # avoid os.path.join relative path bs
my_path_parts = os.path.normpath(my_path.split(':')[1]).split(os.sep)

# do some path cmponent modifications here if you want

if drive_letter: # if drive letter exists
    drive_letter += ':\\'

my_new_path = drive_letter + os.path.join(*my_path_parts)
my_new_path

0voto

Gonzalo Varela Points 1

Sous Windows, en utilisant os.paht.join("/", "Temp") donnera /Temp par défaut, mais aussi étrange que cela puisse paraître, il n'y a aucun problème à utiliser ce chemin comme chemin complet équivalent à "C:/Temp" et cela fonctionne aussi bien pour enregistrer des fichiers que pour en ouvrir.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X