Complément - niveau basique¶
Outre les objets fichiers créés avec la fonction open, comme on l’a vu dans la vidéo, et qui servent à lire et écrire à un endroit précis, une application a besoin d’un minimum d’utilitaires pour parcourir l’arborescence de répertoires et fichiers, c’est notre propos dans ce complément.
Le module os.path (obsolète)¶
Avant la version python-3.4, la librairie standard offrait une conjonction d’outils pour ce type de fonctionnalités:
le module
os.path, pour faire des calculs sur les chemins et noms de fichiers doc,le module
ospour certaines fonctions complémentaires comme renommer ou détruire un fichier doc,et enfin le module
globpour la recherche de fichiers, par exemple pour trouver tous les fichiers en*.txtdoc.
Cet ensemble un peu disparate a été remplacé par une librairie unique pathlib, qui fournit toutes ces fonctionnalités sous un interface unique et moderne, que nous recommandons évidemment d’utiliser pour du nouveau code.
Avant d’aborder pathlib, voici un très bref aperçu de ces trois anciens modules, pour le cas - assez probable - où vous les rencontreriez dans du code existant; tous les noms qui suivent correspondent à des fonctions - par opposition à pathlib qui, comme nous allons le voir, offre une interface orientée objet:
os.path.joinajoute ‘/’ ou '' entre deux morceaux de chemin, selon l’OSos.path.basenametrouve le nom de fichier dans un cheminos.path.dirnametrouve le nom du directory dans un cheminos.path.abspathcalcule un chemin absolu, c’est-à-dire à partir de la racine du filesystem
os.path.existspour savoir si un chemin existe ou pas (fichier ou répertoire)os.path.isfile(etisdir) pour savoir si un chemin est un fichier (et un répertoire)os.path.getsizepour obtenir la taille du fichieros.path.getatimeet aussigetmtimeetgetctimepour obtenir les dates de création/modification d’un fichier
os.remove(ou son ancien nomos.unlink), qui permet de supprimer un fichieros.rmdirpour supprimer un répertoire (mais qui doit être vide)os.removedirspour supprimer tout un répertoire avec son contenu, récursivement si nécessaireos.renamepour renommer un fichier
glob.globcomme dans par exempleglob.glob("*.txt")
Le module pathlib¶
C’est la méthode recommandée aujourd’hui pour travailler sur les fichiers et répertoires.
Orienté Objet¶
Comme on l’a mentionné pathlib offre une interface orientée objet; mais qu’est-ce que ça veut dire au juste ?
Ceci nous donne un prétexte pour une première application pratique des notions de module (que nous avons introduits en fin de semaine 2) et de classe (que nous allons voir en fin de semaine).
De même que le langage nous propose les types builtin int et str, le module pathlib nous expose un type (on dira plutôt une classe) qui s’appelle Path, que nous allons importer comme ceci:
from pathlib import PathNous allons faire tourner un petit scénario qui va créer un fichier:
# le nom de notre fichier jouet
nom = 'fichier-temoin'Pour commencer, nous allons vérifier si le fichier en question existe.
Pour ça nous créons un objet qui est une instance de la classe Path, comme ceci:
# on crée un objet de la classe Path, associé au nom de fichier
path = Path(nom)Vous remarquez que c’est cohérent avec par exemple:
# transformer un float en int
i = int(3.5)en ce sens que le type (int ou Path) se comporte comme une usine pour créer des objets du type en question.
Quoi qu’il en soit, cet objet path offre un certain nombre de méthodes; pour les voir puisque nous sommes dans un notebook, je vous invite dans la cellule suivante à utiliser l’aide en ligne en appuyant sur la touche ‘Tabulation’ après avoir ajouté un . comme si vous alliez envoyer une méthode à cet objet
path.[taper la touche TAB]et le notebook vous montrera la liste des méthodes disponibles.
# ajouter un . et utilisez la touche <Tabulation>
pathPosixPath('fichier-temoin')Ainsi par exemple on peut savoir si le fichier existe avec la méthode exists()
# au départ le fichier n'existe pas
path.exists()False# si j'écris dedans je le crée
with open(nom, 'w', encoding='utf-8') as output:
output.write('0123456789\n')# et maintenant il existe
path.exists()TrueMétadonnées¶
Voici quelques exemples qui montrent comment accéder aux métadonnées de ce fichier:
# cette méthode retourne (en un seul appel système) les métadonnées agrégées
path.stat()os.stat_result(st_mode=33188, st_ino=34113446, st_dev=2051, st_nlink=1, st_uid=1001, st_gid=1001, st_size=11, st_atime=1769609136, st_mtime=1769609136, st_ctime=1769609136)Pour ceux que ça intéresse, l’objet retourné par cette méthode stat est un namedtuple, que l’on va voir très bientôt.
On accède aux différentes informations comme ceci:
# la taille du fichier en octets est de 11
# car il faut compter un caractère "newline" en fin de ligne
path.stat().st_size11# la date de dernière modification, sous forme d'un nombre
# c'est le nombre de secondes depuis le 1er Janvier 1970
mtime = path.stat().st_mtime
mtime1769609136.3043182# que je peux rendre lisible comme ceci
# en anticipant sur le module datetime
from datetime import datetime
mtime_datetime = datetime.fromtimestamp(mtime)
mtime_datetimedatetime.datetime(2026, 1, 28, 14, 5, 36, 304318)# ou encore, si je formatte pour n'obtenir que
# l'heure et la minute
f"{mtime_datetime:%H:%M}"'14:05'Détruire un fichier¶
# je peux maintenant détruire le fichier
path.unlink()# ou encore mieux, si je veux détruire
# seulement dans le cas où il existe je peux aussi faire
try:
path.unlink()
except FileNotFoundError:
print("no need to remove")no need to remove
# et maintenant il n'existe plus
path.exists()False# je peux aussi retrouver le nom du fichier comme ceci
# attention ce n'est pas une méthode mais un attribut
# c'est pourquoi il n'y a pas de parenthèses
path.name'fichier-temoin'Recherche de fichiers¶
Maintenant je voudrais connaître la liste des fichiers de nom *.json dans le directory data.
La méthode la plus naturelle consiste à créer une instance de Path associée au directory lui-même:
dirpath = Path('./data/')Sur cet objet la méthode glob nous retourne un itérable qui contient ce qu’on veut:
# tous les fichiers *.json dans le répertoire data/
for json in dirpath.glob("*.json"):
print(json)data/marine-e2-abb.json
data/marine-e2-ext.json
data/cities_idf.json
data/cities_world.json
data/marine-e1-ext.json
data/cities_europe.json
data/marine-e1-abb.json
data/cities_france.json
Documentation complète¶
Voyez la documentation complète ici
Complément - niveau avancé¶
Pour ceux qui sont déjà familiers avec les classes, j’en profite pour vous faire remarquer le type de notre objet path
type(path)pathlib.PosixPathqui n’est pas Path, mais en fait une sous-classe de Path qui est - sur la plateforme du MOOC au moins, qui fonctionne sous linux - un objet de type PosixPath, qui est une sous-classe de Path, comme vous pouvez le voir:
from pathlib import PosixPath
issubclass(PosixPath, Path)TrueCe qui fait que mécaniquement, path est bien une instance de Path
isinstance(path, Path)Truece qui est heureux puisqu’on avait utilisé Path() pour construire l’objet path au départ :)