web-dev-qa-db-fra.com

Incompréhension de python os.path.abspath

J'ai le code suivant:

directory = r'D:\images'
for file in os.listdir(directory):
    print(os.path.abspath(file))

et je veux la prochaine sortie:

  • D:\images\img1.jpg
  • D:\images\img2.jpg et ainsi de suite

Mais j'obtiens un résultat différent:

  • D:\code\img1.jpg
  • D:\code\img2.jpg

où D:\code est mon répertoire de travail actuel et ce résultat est le même que

os.path.normpath(os.path.join(os.getcwd(), file))

Donc, la question est: quel est le but de os.path.abspath alors que je dois utiliser

os.path.normpath(os.path.join(directory, file))

obtenir le VRAI chemin absolu de mon fichier? Si possible, montrez des cas d'utilisation réels.

22
Most Wanted

Le problème vient de votre compréhension de os.listdir() et non os.path.abspath(). os.listdir() renvoie les noms de chacun des fichiers du répertoire. Cela vous donnera:

img1.jpg
img2.jpg
...

Lorsque vous les passez à os.path.abspath(), ils sont considérés comme des chemins relatifs. Cela signifie qu'il est relatif au répertoire à partir duquel vous exécutez votre code. C'est pourquoi vous obtenez "D:\code\img1.jpg".

Au lieu de cela, ce que vous voulez faire, c'est joindre les noms de fichiers avec le chemin de répertoire que vous répertoriez.

os.path.abspath(os.path.join(directory, file))
34
unholysampler

listdir produit les noms de fichiers in un répertoire, sans référence au nom du répertoire lui-même. Sans aucune autre information, abspath ne peut former un chemin absolu qu'à partir du seul répertoire qu'il connaît: le répertoire de travail courant. Vous pouvez toujours changer le répertoire de travail avant votre boucle:

os.chdir(directory)
for f in os.listdir('.'):
    print(os.path.abspath(f))
5
chepner

Native de Python os.listdir et os.path les fonctions sont de bas niveau. L'itération dans un répertoire (ou une série de répertoires décroissants) nécessite que votre programme assemble les chemins de fichiers manuellement. Il peut être pratique de définir une fonction utilitaire qui génère les chemins dont vous aurez besoin une seule fois, afin que la logique d'assemblage de chemin ne soit pas répétée à chaque itération de répertoire. Par exemple:

import os

def better_listdir(dirpath):
    """
    Generator yielding (filename, filepath) tuples for every
    file in the given directory path.
    """
    # First clean up dirpath to absolutize relative paths and
    # symbolic path names (e.g. `.`, `..`, and `~`)
    dirpath = os.path.abspath(os.path.expanduser(dirpath))

    # List out (filename, filepath) tuples
    for filename in os.listdir(dirpath):
        yield (filename, os.path.join(dirpath, filename))

if __name__ == '__main__':
    for fname, fpath in better_listdir('~'):
        print fname, '->', fpath

Alternativement, il existe des modules de chemin d'accès "de niveau supérieur" que l'on peut utiliser, tels que py.path , path.py , et pathlib (maintenant une partie standard de Python, pour la version 3.4 et supérieure, mais disponible pour la version 2.7). Ceux-ci ajoutent des dépendances à votre projet, mais améliorent de nombreux aspects de la gestion des fichiers, des noms de fichiers et des chemins de fichiers.

3
Jonathan Eunice