Gestion des chemins de fichiers et de répertoires
Pour une plongée approfondie dans les opérations pratiques du système de fichiers, consultez notre article de blog : 10 Opérations Essentielles du Système de Fichiers que Tout Développeur Devrait Connaître.
Il existe deux modules principaux en Python qui traitent de la manipulation des chemins. L’un est le module os.path et l’autre est le module pathlib.
Pathlib vs Module OS
pathlib offre beaucoup plus de fonctionnalités que celles énumérées ci-dessus, comme obtenir le nom du fichier, obtenir l'extension du fichier, lire/écrire un fichier sans l'ouvrir manuellement, etc. Consultez la documentation officielle si vous souhaitez en savoir plus.
Chemins Linux et Windows
Sous Windows, les chemins sont écrits en utilisant des barres obliques inverses (\) comme séparateur entre les noms de dossiers. Sur les systèmes d’exploitation basés sur Unix tels que macOS, Linux et BSD, la barre oblique avant (/) est utilisée comme séparateur de chemin. Joindre des chemins peut être un casse-tête si votre code doit fonctionner sur différentes plateformes.
Heureusement, le module pathlib de Python fournit un moyen facile de gérer cela.
Utilisation de pathlib sur *nix :
# pathlib.Path: gestion de chemins multiplateformes
from pathlib import Path
print(Path('usr').joinpath('bin').joinpath('spam')) # Joindre des composants de chemin
usr/bin/spam
pathlib fournit également un raccourci pour joinpath en utilisant l’opérateur / :
# Opérateur Path (/): moyen pratique de joindre des chemins (multiplateforme)
from pathlib import Path
print(Path('usr') / 'bin' / 'spam') # Utiliser l'opérateur / au lieu de joinpath()
usr/bin/spam
Remarquez que le séparateur de chemin est différent entre Windows et les systèmes d’exploitation basés sur Unix, c’est pourquoi vous voulez utiliser pathlib au lieu d’ajouter des chaînes de caractères ensemble pour joindre des chemins.
Connectez-vous pour répondre à ce quiz et suivre votre progression d'apprentissage
Path('usr') + 'bin' + 'spam'Path('usr') / 'bin' / 'spam'Path('usr').join('bin').join('spam')Path('usr/bin/spam')Joindre des chemins est utile si vous avez besoin de créer différents chemins de fichiers sous le même répertoire.
Utilisation de pathlib sur *nix :
# Path.home(): obtenir le répertoire personnel de l'utilisateur, combiner avec des noms de fichiers
my_files = ['accounts.txt', 'details.csv', 'invite.docx']
home = Path.home() # Obtenir le chemin du répertoire personnel
for filename in my_files:
print(home / filename) # Combiner le chemin personnel avec chaque nom de fichier
/home/labex/project/accounts.txt
/home/labex/project/details.csv
/home/labex/project/invite.docx
Expansion du répertoire personnel de l’utilisateur
Utilisation de os.path.expanduser() pour développer ~ en répertoire personnel de l’utilisateur :
import os.path
# Développer ~ en répertoire personnel de l'utilisateur
print(os.path.expanduser('~'))
/home/labex/project
# Développer ~/Documents en chemin complet
print(os.path.expanduser('~/Documents'))
/home/labex/project/Documents
# Fonctionne avec les chemins contenant ~
print(os.path.expanduser('~/myfile.txt'))
/home/labex/project/myfile.txt
Le répertoire de travail actuel
Vous pouvez obtenir le répertoire de travail actuel en utilisant pathlib :
# Path.cwd(): obtenir le répertoire de travail actuel
from pathlib import Path
print(Path.cwd()) # Retourne le répertoire de travail actuel sous forme d'objet Path
/home/labex/project
Création de nouveaux dossiers
Utilisation de pathlib sur *nix :
from pathlib import Path
cwd = Path.cwd()
(cwd / 'delicious' / 'walnut' / 'waffles').mkdir()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/pathlib.py", line 1226, in mkdir
self._accessor.mkdir(self, mode)
File "/usr/lib/python3.6/pathlib.py", line 387, in wrapped
return strfunc(str(pathobj), *args)
FileNotFoundError: [Errno 2] No such file or directory: '/home/labex/project/delicious/walnut/waffles'
Oh non, nous avons une erreur gênante ! La raison est que le répertoire ‘delicious’ n’existe pas, nous ne pouvons donc pas créer les répertoires ‘walnut’ et ‘waffles’ en dessous. Pour corriger cela, faites :
# mkdir(parents=True): créer le répertoire et tous les répertoires parents si nécessaire
from pathlib import Path
cwd = Path.cwd()
(cwd / 'delicious' / 'walnut' / 'waffles').mkdir(parents=True) # Créer des répertoires imbriqués
Et tout va bien :)
Chemins absolus vs relatifs
Il existe deux façons de spécifier un chemin de fichier.
- Un chemin absolu, qui commence toujours par le dossier racine
- Un chemin relatif, qui est relatif au répertoire de travail actuel du programme
Il existe également les dossiers point (.) et double point (..). Ce ne sont pas de vrais dossiers, mais des noms spéciaux qui peuvent être utilisés dans un chemin. Un seul point (“dot”) pour un nom de dossier est un raccourci pour “ce répertoire”. Deux points (“dot-dot”) signifient “le dossier parent”.
Gestion des chemins absolus
Pour voir si un chemin est un chemin absolu en utilisant pathlib :
from pathlib import Path
Path('/').is_absolute()
True
Path('..').is_absolute()
False
Connectez-vous pour répondre à ce quiz et suivre votre progression d'apprentissage
Path('/').is_absolute() ?TrueFalseNone'/'Vous pouvez extraire un chemin absolu avec pathlib :
from pathlib import Path
print(Path.cwd())
/home/labex/project
print(Path('..').resolve())
/home
Gestion des chemins relatifs
Vous pouvez obtenir un chemin relatif à partir d’un chemin de départ vers un autre chemin en utilisant pathlib :
from pathlib import Path
print(Path('/etc/passwd').relative_to('/'))
etc/passwd
Validité du chemin et du fichier
Vérification de l’existence d’un fichier/répertoire
Utilisation de pathlib sur *nix :
from pathlib import Path
Path('.').exists()
True
Path('setup.py').exists()
True
Path('/etc').exists()
True
Path('nonexistentfile').exists()
False
Vérification si un chemin est un fichier
Utilisation de pathlib sur *nix :
from pathlib import Path
Path('setup.py').is_file()
True
Path('/home').is_file()
False
Path('nonexistentfile').is_file()
False
Connectez-vous pour répondre à ce quiz et suivre votre progression d'apprentissage
Path('setup.py').is_file() si setup.py existe ?'setup.py'FalseTrueNoneVérification si un chemin est un répertoire
Utilisation de pathlib sur *nix :
from pathlib import Path
Path('/').is_dir()
True
Path('setup.py').is_dir()
False
Path('/spam').is_dir()
False
Obtention de la taille d’un fichier en octets
Utilisation de pathlib sur *nix :
from pathlib import Path
stat = Path('/bin/python3.6').stat()
print(stat) # stat contient également d'autres informations sur le fichier
os.stat_result(st_mode=33261, st_ino=141087, st_dev=2051, st_nlink=2, st_uid=0,
--snip--
st_gid=0, st_size=10024, st_atime=1517725562, st_mtime=1515119809, st_ctime=1517261276)
print(stat.st_size) # taille en octets
10024
Listage des répertoires
Listage du contenu d’un répertoire en utilisant pathlib sur *nix :
from pathlib import Path
for f in Path('/usr/bin').iterdir():
print(f)
...
/usr/bin/tiff2rgba
/usr/bin/iconv
/usr/bin/ldd
/usr/bin/cache_restore
/usr/bin/udiskie
/usr/bin/unix2dos
/usr/bin/t1reencode
/usr/bin/epstopdf
/usr/bin/idle3
...
Tailles de fichiers de répertoire
ATTENTION
Les répertoires eux-mêmes ont également une taille ! Vous voudrez donc vérifier si un chemin est un fichier ou un répertoire en utilisant les méthodes discutées dans la section précédente.
Utilisation de pathlib sur *nix :
from pathlib import Path
total_size = 0
for sub_path in Path('/usr/bin').iterdir():
total_size += sub_path.stat().st_size
print(total_size)
1903178911
Copie de fichiers et de dossiers
Le module shutil fournit des fonctions pour copier des fichiers, ainsi que des dossiers entiers.
import shutil
shutil.copy('/tmp/spam.txt', '/tmp/delicious')
/tmp/delicious/spam.txt
shutil.copy('/tmp/eggs.txt', '/tmp/delicious/eggs2.txt')
/tmp/delicious/eggs2.txt
Connectez-vous pour répondre à ce quiz et suivre votre progression d'apprentissage
shutil.copy()Path.copy()os.copy()shutil.copytree()Alors que shutil.copy() copiera un seul fichier, shutil.copytree() copiera un dossier entier et tous les dossiers et fichiers qu’il contient :
import shutil
shutil.copytree('/tmp/bacon', '/tmp/bacon_backup')
/tmp/bacon_backup
Déplacement et renommage
import shutil
shutil.move('/tmp/bacon.txt', '/tmp/eggs')
/tmp/eggs/bacon.txt
Le chemin de destination peut également spécifier un nom de fichier. Dans l’exemple suivant, le fichier source est déplacé et renommé :
shutil.move('/tmp/bacon.txt', '/tmp/eggs/new_bacon.txt')
/tmp/eggs/new_bacon.txt
S’il n’y a pas de dossier eggs, alors move() renommera bacon.txt en un fichier nommé eggs :
shutil.move('/tmp/bacon.txt', '/tmp/eggs')
/tmp/eggs
Suppression de fichiers et de dossiers
- Appeler
Path.unlink()supprimera le fichier au chemin spécifié. - Appeler
Path.rmdir()supprimera le dossier au chemin spécifié. Ce dossier doit être vide de tout fichier ou dossier. - Appeler
shutil.rmtree(path)supprimera le dossier au chemin spécifié, et tous les fichiers et dossiers qu’il contient seront également supprimés.
Connectez-vous pour répondre à ce quiz et suivre votre progression d'apprentissage
Path.rmdir()shutil.rmtree()Path.unlink()os.remove()Parcours d’une arborescence de répertoires
L’objet Path possède une méthode rglob() pour itérer récursivement sur les fichiers et les répertoires.
from pathlib import Path
p = Path('/tmp/delicious')
for i in p.rglob('*'):
print(i)
/tmp/delicious/cats
/tmp/delicious/walnut
/tmp/delicious/spam.txt
/tmp/delicious/cats/catnames.txt
/tmp/delicious/cats/zophie.jpg
/tmp/delicious/walnut/waffles
/tmp/delicious/walnut/waffles/butter.txt