Accéder au contenu principal

Un guide complet de l'utilisation de pathlib en Python pour la manipulation du système de fichiers

Découvrez les avantages de la pathlib de Python par rapport au module os en explorant les objets de chemin, les composants de chemin et les opérations de chemin courantes pour l'interaction avec le système de fichiers.
Actualisé 16 janv. 2025  · 9 min de lecture

Jusqu'à récemment, la manipulation du système de fichiers en Python était notoirement difficile. Les développeurs étaient souvent confrontés à des chemins d'accès incorrects, qui étaient sujets à des erreurs parce qu'ils nécessitaient de longues chaînes de caractères en entrée. En outre, les développeurs ont signalé que leur code se cassait fréquemment en raison d'incohérences entre les différents systèmes d'exploitation.

Heureusement, dans la version 3.4 de Python, les développeurs ont introduit le module pathlib dans la bibliothèque standard. pathlib fournit une solution élégante pour gérer les chemins d'accès au système de fichiers à l'aide d'une approche orientée objet attendue depuis longtemps, et il garantit également un comportement agnostique par rapport à la plateforme.

Ce tutoriel complet vous apprendra les fonctionnalités du module pathlib pour vous aider dans vos interactions quotidiennes avec votre système de fichiers. En utilisant pathlib, vous bénéficierez de flux de travail efficaces et d'une récupération aisée des données. pathlib a considérablement évolué au fil des ans, et nous l'avons mis à jour pour que vous n'ayez pas à le faire. Commençons.

Module os de Python vs. pathlib

Avant Python 3.4, la manière la plus traditionnelle de gérer les chemins d'accès aux fichiers consistait à utiliser le module os. Alors que le module os était autrefois très efficace, il a commencé à faire son temps.

Nous pouvons montrer la valeur unique de pathlib en considérant une tâche courante en science des données : comment trouver tous les fichiers png dans un répertoire donné et dans tous ses sous-répertoires.

Si nous utilisions le module os, nous pourrions écrire le code suivant :

import os
dir_path = "/home/user/documents"
files = [
os.path.join(dir_path, f)
for f in os.listdir(dir_path)
if os.path.isfile(os.path.join(dir_path, f)) and f.endswith(".png")
]

Bien que ce code résolve la tâche immédiate de trouver nos fichiers png, il révèle plusieurs inconvénients majeurs du module os. D'une part, le code est long et presque illisible, ce qui est dommage, s'agissant d'une opération relativement simple. Deuxièmement, notre code suppose une connaissance des compréhensions de listes, ce qui ne devrait pas être considéré comme acquis. Troisièmement, le code implique des opérations sur les chaînes de caractères, qui sont sujettes à des erreurs. De plus, le code n'est pas très concis. 

Si nous utilisions plutôt le module pathlib, notre code serait beaucoup plus simple. Comme nous l'avons mentionné, pathlib propose une approche orientée objet pour gérer les chemins d'accès au système de fichiers. Jetez un coup d'œil :

from pathlib import Path

# Create a path object
dir_path = Path(dir_path)

# Find all text files inside a directory
files = list(dir_path.glob("*.png"))

Cette programmation orientée objet organise le code autour des objets et de leurs interactions, ce qui permet d'obtenir un code plus modulaire, plus réutilisable et plus facile à maintenir. Si vous n'êtes pas familier avec la programmation orientée objet, cela vaut la peine d'apprendre avec notrecours Programmation orientée objet en Python.

Travailler avec des objets Path en Python

La bibliothèque pathlib s'articule autour de ce que l'on appelle les objets Path, qui représentent les chemins d'accès au système de fichiers d'une manière structurée et indépendante de la plate-forme.

Plus tôt dans ce tutoriel, nous avons amené la classe Path du module pathlib dans notre espace de noms actuel à l'aide de la ligne de code suivante :

from pathlib import Path

Après avoir appelé la classe Path à partir de pathlib, nous pouvons créer des objets Path de différentes manières, notamment à partir de chaînes de caractères, d'autres objets Path, du répertoire de travail actuel et du répertoire personnel.

Examinons-les l'une après l'autre.

Création d'objets chemin à partir de chaînes de caractères

Nous pouvons créer un objet Path en passant une chaîne de caractères représentant un chemin d'accès au système de fichiers à une variable. Cette opération convertit la représentation sous forme de chaîne du chemin d'accès au fichier en un objet Path.

file_path_str = "data/union_data.csv"

data_path = Path(file_path_str)

Création d'objets chemin à partir d'autres objets chemin

Les objets Path existants peuvent servir d'éléments de base pour la création de nouveaux chemins. 

Pour ce faire, nous combinons un chemin de base, un répertoire de données et un nom de fichier en un seul chemin de fichier. Nous devons nous rappeler d'utiliser une barre oblique lorsque cela est nécessaire pour étendre nos objets Path.

base_path = Path("/home/user")
data_dir = Path("data")

# Combining multiple paths
file_path = base_path / data_dir / "prices.csv"  
print(file_path)
'/home/user/data/prices.csv'

Création d'objets chemin à partir du répertoire de travail actuel

Ici, nous assignons le répertoire de travail actuel à la variable cwd en utilisant la méthode Path.cwd(). Nous pouvons alors récupérer le chemin du répertoire de travail actuel dans lequel notre script s'exécute. 

cwd = Path.cwd()

print(cwd)
'/home/bexgboost/articles/2024/4_april/8_pathlib'

Création d'objets chemin à partir du répertoire de travail personnel

Nous pouvons construire un chemin en combinant notre répertoire personnel avec des sous-répertoires supplémentaires. Ici, nous combinons notre répertoire personnel avec les sous-répertoires "downloads" et "projects". 

home = Path.home()

home / "downloads" / "projects"
PosixPath('/home/bexgboost/downloads/projects')

Une remarque importante : La classe Path elle-même n'effectue aucune opération sur le système de fichiers, comme la validation du chemin d'accès, la création de répertoires ou de fichiers. Il est conçu pour représenter et manipuler des chemins. Pour interagir réellement avec le système de fichiers (vérifier l'existence, lire/écrire des fichiers), nous devrons utiliser des méthodes spéciales des objets Path et, pour certains cas avancés, obtenir l'aide du module os.

Travailler avec des composants de chemin d'accès en Python

Les attributs de chemin de fichier sont des propriétés et des composants variés d'un chemin de fichier qui aident à identifier et à gérer les fichiers et les répertoires au sein d'un système de fichiers. Tout comme une adresse physique se compose de différents éléments, tels que le numéro de rue, la ville, le pays et le code postal, un chemin d'accès à un système de fichiers peut être décomposé en éléments plus petits. pathlib nous permet d'accéder à ces éléments et de les manipuler en utilisant les attributs de chemin d'accès par le biais de la notation par points.

Travailler avec le répertoire racine

La racine est le répertoire le plus élevé d'un système de fichiers. Dans les systèmes de type Unix, il est représenté par une barre oblique (/). Sous Windows, il s'agit généralement d'une lettre de lecteur suivie de deux points, comme C:.

image_file = home / "downloads" / "midjourney.png"

image_file.root
'/'

Travailler avec le répertoire parent

Le parent contient le fichier ou le répertoire actuel. Il se situe à un niveau supérieur par rapport au répertoire ou au fichier actuel. 

image_file.parent
PosixPath('/home/bexgboost/downloads')

Travailler avec le nom du fichier

Cet attribut renvoie le nom complet du fichier, y compris l'extension, sous la forme d'une chaîne de caractères.

image_file.name
'midjourney.png'

Travailler avec le suffixe du fichier

L'attribut suffixe renvoie l'extension du fichier, y compris le point, sous la forme d'une chaîne (ou d'une chaîne vide s'il n'y a pas d'extension).

image_file.suffix
'.png'

Travailler avec la tige du fichier

La tige renvoie le nom du fichier sans l'extension. L'utilisation de la tige peut s'avérer utile pour convertir des fichiers en différents formats.

image_file.stem
'midjourney'

Note : Sur un Mac, les chemins d'accès aux fichiers sont sensibles à la casse, de sorte que /Users/username/Documents et /users/username/documents seraient différents. 

L'attribut pathlib parts

Nous pouvons utiliser l'attribut .parts pour diviser un objet Path en ses composants.

image_file.parts
('/', 'home', 'bexgboost', 'downloads', 'midjourney.png')

L'attribut pathlib parents

L'attribut parents, qui renvoie un générateur, transforme ces composants en objets Path

list(image_file.parents)
[PosixPath('/home/bexgboost/downloads'),
PosixPath('/home/bexgboost'),
PosixPath('/home'),
PosixPath('/')]

Opérations courantes sur les chemins d'accès à l'aide de pathlib

Path possèdent de nombreuses méthodes qui vous permettent d'interagir efficacement avec les répertoires et leur contenu. Voyons comment effectuer certaines des opérations les plus courantes.

Répertoires de listes

La méthode iterdir() vous permet de parcourir tous les fichiers et sous-répertoires d'un dossier. Elle est particulièrement utile pour traiter tous les fichiers d'un répertoire ou pour effectuer des opérations sur chaque entrée.

cwd = Path.cwd()
 for entry in cwd.iterdir():
# Process the entry here
...
# print(entry)

Comme iterdir() renvoie un itérateur, les entrées sont récupérées à la demande au fur et à mesure que vous parcourez la boucle.

La méthode is_dir()

La méthode is_dir() renvoie True si le chemin pointe vers un répertoire, False dans le cas contraire.

for entry in cwd.iterdir():
   if entry.is_dir():
      print(entry.name)
.ipynb_checkpoints
data
images

La méthode is_file()

La méthode .is_file() renvoie True si le chemin pointe vers un fichier, False sinon.

for entry in cwd.iterdir():
   if entry.is_file():
      print(entry.suffix)
.ipynb
.txt

La méthode exists()

Étant donné que les objets Path ne représentent que des chemins, vous devez parfois vérifier l'existence d'un chemin à l'aide de la méthode .exists():

La méthode .exists() vérifie si un chemin existe. Ceci est utile car les objets Path peuvent représenter des fichiers et des répertoires qui peuvent ou non être réellement présents dans le système de fichiers.

image_file.exists()
False

Création et suppression de chemins

pathlib offre également des fonctionnalités de création et de suppression de fichiers et de répertoires. Voyons comment.

La méthode mkdir()

La méthode mkdir() crée un nouveau répertoire au chemin spécifié. Par défaut, il crée le répertoire dans le répertoire de travail actuel.

from pathlib import Path

data_dir = Path("new_data_dir")

# Create the directory 'new_data_dir' in the current working directory
data_dir.mkdir()

La méthode mkdir(parents=True)

La méthode mkdir(parents=True) est particulièrement utile lorsque vous souhaitez créer une structure de répertoires dans laquelle certains répertoires parents n'existent pas. Le fait de définir parents=True permet de s'assurer que tous les répertoires parents nécessaires sont créés en cours de route.

sub_dir = Path("data/nested/subdirectory")

# Create 'data/nested/subdirectory', even if 'data' or 'nested' don't exist
sub_dir.mkdir(parents=True)

N'oubliez pas que mkdir() soulève une exception si un répertoire portant le même nom existe déjà.

Path('data').mkdir()
FileExistsError: [Errno 17] File exists: 'data'

La méthode unlink()

La méthode unlink() supprime définitivement un fichier représenté par l'objet Path. Il est recommandé de vérifier si un fichier existe avant d'exécuter cette méthode afin d'éviter de recevoir une erreur.

to_delete = Path("data/prices.csv")

if to_delete.exists():
   to_delete.unlink()
   print(f"Successfully deleted {to_delete.name}")
Successfully deleted prices.csv

La méthode rmdir()

La méthode rmdir() supprime un répertoire vide. N'oubliez pas que rmdir() ne fonctionne que pour supprimer les répertoires vides. La manière la plus simple de supprimer un répertoire non vide est d'utiliser la bibliothèque shutil ou le terminal.

empty_dir = Path("new_data_dir")

empty_dir.rmdir()

Note : Soyez prudent lorsque vous utilisez unlink() ou rmdir() car leurs résultats sont permanents.

Manipulation avancée des chemins

Passons maintenant à des concepts avancés de manipulation de chemins et à leur mise en pratique à l'aide de pathlib.

Chemins relatifs ou absolus

Nous commencerons par comprendre les différences entre les chemins absolus et relatifs, car elles reviennent souvent.

Chemins relatifs

Les chemins relatifs indiquent l'emplacement d'un fichier ou d'un répertoire par rapport au répertoire actuel, d'où le terme "relatif". Ils sont courts et flexibles au sein de votre projet, mais peuvent être source de confusion si vous changez de répertoire de travail.

Par exemple, j'ai un dossier images dans mon répertoire de travail actuel, qui contient le fichier midjourney.png.

image = Path("images/midjourney.png")

image
PosixPath('images/midjourney.png')

Le code ci-dessus fonctionne maintenant, mais si je déplace l'ordinateur portable que j'utilise vers un autre endroit, le snippet sera interrompu parce que le dossier des images n'a pas été déplacé avec l'ordinateur portable.

Chemins absolus

Les chemins d'accès absolus indiquent l'emplacement complet d'un fichier ou d'un répertoire à partir de la racine du système de fichiers. Ils sont indépendants du répertoire courant et offrent un point de référence clair à tout utilisateur, où qu'il se trouve dans le système.

image_absolute = Path("/home/bexgboost/articles/2024/4_april/8_pathlib/images/midjourney.png")

image_absolute
PosixPath('/home/bexgboost/articles/2024/4_april/8_pathlib/images/midjourney.png')

Comme vous pouvez le constater, les chemins absolus peuvent être assez longs, en particulier dans les projets complexes avec des structures arborescentes imbriquées. C'est pourquoi la plupart des gens préfèrent les chemins relatifs qui sont plus courts.

Méthode de résolution

pathlib fournit des méthodes pour convertir les chemins relatifs en chemins absolus avec la méthode resolve().

relative_image = Path("images/midjourney.png")

absolute_image = relative_image.resolve()

absolute_image
PosixPath('/home/bexgboost/articles/2024/4_april/8_pathlib/images/midjourney.png')

On peut aussi aller dans l'autre sens : Si nous disposons d'un chemin d'accès absolu, nous pouvons le convertir en chemin d'accès relatif sur la base d'un répertoire de référence.

relative_path = Path.cwd()

absolute_image.relative_to(relative_path)
PosixPath('images/midjourney.png')

Globbing

Afin d'illustrer le globbing, nous pouvons revenir à l'exemple que nous avons présenté au début de l'article, où nous avons écrit du code pour trouver tous les fichiers png dans un répertoire donné.

files = list(dir_path.glob("*.png"))

pathlib utilise le module intégré .glob() pour rechercher efficacement les fichiers correspondant à un modèle spécifique dans n'importe quel répertoire. Ce module est très utile pour traiter des fichiers dont les noms ou les extensions sont similaires.

La méthode glob accepte en entrée une chaîne de caractères contenant des caractères génériques et renvoie un objet générateur qui produit à la demande des objets Path correspondants :

  • *: Correspond à zéro ou plusieurs caractères.

  • ?: Correspond à n'importe quel caractère unique.

  • []: Correspond à une plage de caractères entre crochets (par exemple, [a-z] correspond à n'importe quelle lettre minuscule).

Pour illustrer, essayons de trouver tous les notebooks Jupyter dans mon répertoire d'articles.

articles_dir = Path.home() / "articles"

# Find all scripts
notebooks = articles_dir.glob("*.ipynb")

# Print how many found
print(len(list(notebooks)))
0

La méthode .glob() n'a trouvé aucun carnet de notes, ce qui, à première vue, semble surprenant car j'ai écrit plus de 150 articles. La raison en est que .glob() ne recherche que dans le répertoire donné, et non dans ses sous-répertoires.

Nous pouvons résoudre ce problème en effectuant une recherche récursive, pour laquelle nous devons utiliser la méthode rglob(), dont la syntaxe est similaire :

notebooks = articles_dir.rglob("*.ipynb")

print(len(list(notebooks)))
357

Cette fois, notre code a trouvé les 357 fichiers.

Travailler avec des fichiers

Comme nous l'avons vu, les objets Path ne représentent que des fichiers mais n'effectuent pas d'opérations sur ceux-ci. Cependant, ils disposent de certaines méthodes pour les opérations courantes sur les fichiers. Nous verrons comment les utiliser dans cette section.

Lecture des fichiers

La lecture du contenu des fichiers est une opération fondamentale dans de nombreuses applications Python. pathlib fournit des méthodes pratiques pour lire les fichiers sous forme de texte ou d'octets bruts.

La méthode read_text() nous permet de lire le contenu d'un fichier texte et de fermer le fichier.

file = Path("file.txt")

print(file.read_text())
This is sample text.

Pour les fichiers binaires, nous pouvons utiliser la méthode read_bytes().

image = Path("images/midjourney.png")

image.read_bytes()[:10]
b'\x89PNG\r\n\x1a\n\x00\x00'

N'oubliez pas que lorsque vous utilisez une méthode read_*, la gestion des erreurs est importante :

nonexistent_file = Path("gibberish.txt")

try:
   contents = nonexistent_file.read_text()
except FileNotFoundError:
   print("No such thing.")
No such thing.

Écriture de fichiers

L'écriture dans les fichiers est aussi simple que la lecture des fichiers. Pour écrire des fichiers, nous disposons de la méthode write_text().

file = Path("file.txt")

file.write_text("This is new text.")
17
file.read_text()
'This is new text.'

Comme nous pouvons le constater, la méthode write_text() écrase le texte. Bien qu'il n'y ait pas de mode d'ajout pour write_text(), nous pouvons utiliser read_text() et write_text() ensemble pour ajouter du texte à la fin du fichier.

old_text = file.read_text() + "\n"
final_text = "This is the final text."

# Combine old and new texts and write them back
file.write_text(old_text + final_text)

print(file.read_text())
This is new text.

This is the final text.

write_bytes() fonctionne de la même manière. Pour illustrer notre propos, dupliquons d'abord l'image midjourney.png en lui donnant un nouveau nom.

original_image = Path("images/midjourney.png")

new_image = original_image.with_stem("duplicated_midjourney")

new_image
PosixPath('images/duplicated_midjourney.png')

La méthode with_stem() renvoie un chemin d'accès au fichier avec un nom de fichier différent (bien que le suffixe reste le même). Cela nous permet de lire une image originale et d'écrire son contexte dans une nouvelle image. 

new_image.write_bytes(original_image.read_bytes())
1979612

Renommer et déplacer des fichiers

Outre la fonction with_stem() qui permet de renommer la tige d'un fichier, pathlib propose la méthode rename() qui permet de renommer plus complètement. 

file = Path("file.txt")

target_path = Path("new_file.txt")

file.rename(target_path)
PosixPath('new_file.txt')

rename() accepte un chemin cible, qui peut être une chaîne de caractères ou un autre objet chemin.

Pour déplacer des fichiers, vous pouvez utiliser la fonction replace(), qui accepte également un chemin de destination :

# Define the file to be moved
source_file = Path("new_file.txt")

# Define the location to put the file
destination = Path("data/new/location")

# Create the directories if they don't exist
destination.mkdir(parents=True)

# Move the file
source_file.replace(destination / source_file.name)
PosixPath('data/new/location/new_file.txt')

Création de fichiers vierges

pathlib nous permet de créer des fichiers vierges en utilisant la méthode touch:

# Define new file path
new_dataset = Path("data/new.csv")

new_dataset.exists()
False
new_dataset.touch()

new_dataset.exists()
True

La méthode touch a été conçue à l'origine pour mettre à jour l'heure de modification d'un fichier, elle peut donc également être utilisée pour des fichiers existants.

original_image.touch()

Lorsque vous devez réserver un nom de fichier pour un usage ultérieur, mais que vous n'avez pas de contenu à y inscrire pour le moment, vous pouvez utiliser touch pour créer un fichier vierge. Cette méthode s'inspire de la commande de terminal Unix "touch".

Permissions et informations sur le système de fichiers

Enfin, nous apprendrons à accéder aux caractéristiques des fichiers à l'aide de la méthode .stat(). Si vous êtes familier avec os, vous remarquerez que cette nouvelle méthode produit le même résultat que os.stat().

image_stats = original_image.stat()

image_stats
os.stat_result(st_mode=33188, st_ino=1950175, st_dev=2080, st_nlink=1, st_uid=1000, st_gid=1000, st_size=1979612, st_atime=1714664562, st_mtime=1714664562, st_ctime=1714664562)

Nous pouvons également récupérer la taille du fichier en utilisant la notation par points.

image_size = image_stats.st_size

# File size in megabytes
image_size / (1024**2)
1.8879051208496094

Conclusion

L'introduction du module pathlib dans Python 3.4 a considérablement simplifié la manipulation du système de fichiers pour les développeurs. En proposant une approche orientée objet pour gérer les chemins d'accès aux fichiers, pathlib offre un moyen structuré et simple de représenter les chemins d'accès aux systèmes de fichiers. pathlib offre également une indépendance vis-à-vis des plateformes, ce qui signifie que pathlib gère les séparateurs de chemins d'accès de manière cohérente sur différents systèmes d'exploitation, de sorte que notre code ne s'interrompt pas sur une nouvelle machine. Enfin, pathlib offre un vaste ensemble de méthodes concises et expressives pour les opérations courantes du système de fichiers, comme nous l'avons vu. 

N'oubliez pas que pathlib est l'une des nombreuses et puissantes bibliothèques intégrées à Python. En suivant nos cursus Data Scientist With Python Career Track, Python Programming Skill Track et Intro to Python for Data Science, vous maîtriserez un large ensemble de bibliothèques intégrées pour devenir un solide programmeur Python. 

Merci de votre lecture !



Bex Tuychiev's photo
Author
Bex Tuychiev
LinkedIn

Je suis un créateur de contenu en science des données avec plus de 2 ans d'expérience et l'un des plus grands followings sur Medium. J'aime écrire des articles détaillés sur l'IA et la ML dans un style un peu sarcastıc, car il faut bien faire quelque chose pour les rendre un peu moins ennuyeux. J'ai produit plus de 130 articles et un cours DataCamp, et un autre est en cours d'élaboration. Mon contenu a été vu par plus de 5 millions de personnes, dont 20 000 sont devenues des adeptes sur Medium et LinkedIn. 

Sujets

Apprenez Python avec DataCamp

cursus

Python Programming

19hrs hr
Level-up your programming skills. Learn how to optimize code, write functions and tests, and use best-practice software engineering techniques.
Afficher les détailsRight Arrow
Commencer le cours
Voir plusRight Arrow
Apparenté

blog

Les 32 meilleures questions d'entretien sur AWS et leurs réponses pour 2024

Un guide complet pour explorer les questions d'entretien AWS de base, intermédiaires et avancées, ainsi que des questions basées sur des situations réelles. Il couvre tous les domaines, garantissant ainsi une stratégie de préparation bien équilibrée.
Zoumana Keita 's photo

Zoumana Keita

30 min

blog

2022-2023 Rapport annuel DataCamp Classrooms

À l'aube de la nouvelle année scolaire, DataCamp Classrooms est plus motivé que jamais pour démocratiser l'apprentissage des données, avec plus de 7 650 nouveaux Classrooms ajoutés au cours des 12 derniers mois.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

8 min

blog

Q2 2023 DataCamp Donates Digest

DataCamp Donates a offert plus de 20k bourses d'études à nos partenaires à but non lucratif au deuxième trimestre 2023. Découvrez comment des apprenants défavorisés et assidus ont transformé ces opportunités en réussites professionnelles qui ont changé leur vie.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

blog

Les 20 meilleures questions d'entretien pour les flocons de neige, à tous les niveaux

Vous êtes actuellement à la recherche d'un emploi qui utilise Snowflake ? Préparez-vous à répondre à ces 20 questions d'entretien sur le flocon de neige pour décrocher le poste !
Nisha Arya Ahmed's photo

Nisha Arya Ahmed

20 min

blog

Célébration de Saghar Hazinyar : Une boursière de DataCamp Donates et une diplômée de Code to Inspire

Découvrez le parcours inspirant de Saghar Hazinyar, diplômée de Code to Inspire, qui a surmonté les défis en Afghanistan et s'est épanouie grâce à une bourse de DataCamp Donates.
Fereshteh Forough's photo

Fereshteh Forough

4 min

blog

Nous avons fait don de bourses DataCamp Premium à un million de personnes, et ce n'est pas fini.

Réparties entre nos deux programmes d'impact social, DataCamp Classrooms et #DCDonates, les bourses offrent un accès illimité à tout ce que DataCamp Premium a à offrir.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

Voir plusVoir plus