web-dev-qa-db-fra.com

construction d'un chemin absolu avec os.path.join ()

Je voudrais construire un chemin absolu en python, tout en restant assez inconscient de choses comme le séparateur de chemin.

edit0: par exemple, il y a un répertoire à la racine de mon système de fichiers /etc/init.d (ou C:\etc\init.d sur w32), et je veux le construire uniquement à partir des éléments etc et init.d (sur w32, j'ai probablement aussi besoin d'un ID de disque, comme C:)

Afin de ne pas avoir à se soucier des séparateurs de chemin, os.join.path() est évidemment l'outil de choix. Mais il semble que cela ne créera que des chemins relatifs :

 print "MYPATH:", os.path.join('etc', 'init.d')
 MYPATH: etc/init.d

L'ajout d'un premier élément factice (par exemple '') N'aide en rien:

 print "MYPATH:", os.path.join('', 'etc', 'init.d')
 MYPATH: etc/init.d

Rendre le premier élément absolu est évidemment utile, mais ce genre de résultat contredit l'idée d'utiliser os.path.join()

 print "MYPATH:", os.path.join('/etc', 'init.d')
 MYPATH: /etc/init.d

edit1: en utilisant os.path.abspath() essaiera seulement de convertir un chemin relatif en chemin absolu. par exemple. pensez à exécuter ce qui suit dans le répertoire de travail /home/foo:

 print "MYPATH:", os.path.abspath(os.path.join('etc', 'init.d'))
 MYPATH: /home/foo/etc/init.d

Alors, quelle est la méthode standard multiplateforme pour "rooter" un chemin?

 root = ??? # <--
 print "MYPATH:", os.path.join(root, 'etc', 'init.d')
 MYPATH: /etc/init.d

edit2: la question se résume vraiment à ceci: puisque la barre oblique principale dans /etc/init.d fait de ce chemin un chemin absolu, existe-t-il un moyen de construire cette barre oblique principale par programme? (Je ne veux pas faire d'hypothèses qu'une barre oblique principale indique un chemin absolu)

41
umläute

donc la solution que j'ai trouvée, est de construire la racine du système de fichiers en suivant un fichier donné jusqu'à sa racine:

def getRoot(file=None):
  if file is None:
      file='.'
  me=os.path.abspath(file)
  drive,path=os.path.splitdrive(me)
  while 1:
    path,folder=os.path.split(path)
    if not folder:
       break
  return drive+path

 os.path.join(getRoot(), 'etc', 'init.d')
2
umläute

L'utilisation de os.sep En tant que root a fonctionné pour moi:

path.join(os.sep, 'python', 'bin')

Linux: /python/bin

Windows: \python\bin

L'ajout de path.abspath() au mixage vous donnera également des lettres de lecteur sous Windows et est toujours compatible avec Linux:

path.abspath(path.join(os.sep, 'python', 'bin'))

Linux: /python/bin

Windows: C:\python\bin

58
girardc79

Je pense que vous pouvez utiliser os.path.normpath. Voici ce que j'obtiens sur Windows:

>>> os.path.normpath("/etc/init.d")
'\\etc\\init.d'

Je ne sais pas exactement quelle est la bonne chose à faire avec le préfixe de lecteur, mais je pense que le laisser signifie quelque chose comme "continuez à utiliser le lecteur sur lequel je suis maintenant", ce qui est probablement ce que vous voulez. Peut-être que quelqu'un plus familier avec Windows peut clarifier?

4
Jack O'Connor

Vous pouvez donc vérifier l'exécution de os par sys.platform

sur les fenêtres

>>> sys.platform
'win32'

sous linux

>>> sys.platform
'linux2'

puis

if sys.platform == 'win32':
    ROOT = os.path.splitdrive(os.path.abspath('.'))[0]
Elif sys.platform == 'linux2':
    ROOT = os.sep

Veuillez noter que "linux2" peut ne pas couvrir toutes les distributions linux

1
Ansuman Bebarta