Le module os.path a de nombreuses fonctions pour manipuler les chemins de fichiers et de répertoires. Ici nous voulons gérer les chemins et
lister le contenu d'un répertoire.
Exemple 6.16. Construction de noms de chemins
>>> import os>>> os.path.join("c:\\music\\ap\\", "mahadeva.mp3")'c:\\music\\ap\\mahadeva.mp3'>>> os.path.join("c:\\music\\ap", "mahadeva.mp3")'c:\\music\\ap\\mahadeva.mp3'>>> os.path.expanduser("~")'c:\\Documents and Settings\\mpilgrim\\My Documents'>>> os.path.join(os.path.expanduser("~"), "Python")'c:\\Documents and Settings\\mpilgrim\\My Documents\\Python'
os.path est une
référence à un module, quel module exactement dépend de la
plateforme que vous utilisez. Tout comme getpass encapsule les
différences entre plateforme en assignant à
getpass une fonction spécifique à la
plateforme, os encapsule
les différences entre plateformes en assignant à
path un module spécifique à la
plateforme.
La fonction join de os.path construit un nom de chemin à
partir d’un ou de plusieurs noms de chemins partiels. Dans ce cas
simple il ne fait que concaténer des chaînes (notez que traiter
des noms de chemins sous Windows est ennuyeux car le backslash
force à utiliser le caractère d’échappement).
Dans cette exemple un peu moins simple, join
ajoute un backslash supplémentaire au
nom de chemin avant de le joindre au nom de fichier. J’étais ravi
quand j’ai découvert cela car
addSlashIfNecessary est une des petites
fonctions stupides que je dois toujours écrire quand je construis
ma boîte à outil dans un nouveau langage. N’écrivez
pas cette petite fonction stupide en
Python, des gens intelligents l’ont
déjà fait pour vous.
expanduser développe un nom de chemin
qui utilise ~ pour représenter le répertoire de
l’utilisateur. Cela fonctionne sur toutes les plateformes où les
utilisateurs ont un répertoire propre comme Windows,
UNIX et MacOS X, c'est sans effet sous
MacOS.
En combinant ces techniques, vous pouvez facilement
construire des noms de chemins pour les répertoires et les
fichiers contenus dans le répertoire utilisateur.
La fonction split divise un nom de
chemin complet et retourne un tuple contenant le chemin et le nom
de fichier. Vous vous rappelez quand je vous ai dit que vous
pouviez utiliser l’assignement multiple de
variables pour retourner des valeurs multiples d’une
fonction ? Et bien split est une de ces
fonctions.
Nous assignons la valeur de retour de la fonction
split à un tuple de deux variables. Chaque
variable reçoit la valeur de l’élément correspondant du tuple
retourné.
La première variable, filepath, reçoit la
valeur du premier élément du tuple retourné par
split, le chemin du fichier.
La seconde variable, filename, reçoit la
valeur du second élément du tuple retourné par
split, le nom de fichier.
os.path contient
aussi une fonction splitext, qui divise un
nom de fichier et retourne un tuple contenant le nom de fichier et
l’extension. Nous utilisons la même technique pour assigner chacun
d’entre eux à des variables séparées.
Exemple 6.18. Liste des fichiers d’un répertoire
>>> os.listdir("c:\\music\\_singles\\")['a_time_long_forgotten_con.mp3', 'hellraiser.mp3',
'kairo.mp3', 'long_way_home1.mp3', 'sidewinder.mp3',
'spinning.mp3']>>> dirname = "c:\\">>> os.listdir(dirname)['AUTOEXEC.BAT', 'boot.ini', 'CONFIG.SYS', 'cygwin',
'docbook', 'Documents and Settings', 'Incoming', 'Inetpub', 'IO.SYS',
'MSDOS.SYS', 'Music', 'NTDETECT.COM', 'ntldr', 'pagefile.sys',
'Program Files', 'Python20', 'RECYCLER',
'System Volume Information', 'TEMP', 'WINNT']>>> [f for f in os.listdir(dirname)... if os.path.isfile(os.path.join(dirname, f))]['AUTOEXEC.BAT', 'boot.ini', 'CONFIG.SYS', 'IO.SYS', 'MSDOS.SYS',
'NTDETECT.COM', 'ntldr', 'pagefile.sys']>>> [f for f in os.listdir(dirname)... if os.path.isdir(os.path.join(dirname, f))]['cygwin', 'docbook', 'Documents and Settings', 'Incoming',
'Inetpub', 'Music', 'Program Files', 'Python20', 'RECYCLER',
'System Volume Information', 'TEMP', 'WINNT']
La fonction listdir prend un nom de
chemin et retourne une liste du contenu du répertoire.
listdir retourne à la fois les fichiers
et les répertoires, sans indiquer lequel est quoi.
Vous pouvez utiliser le filtrage de liste et la fonction
isfile du module os.path pour séparer les fichiers
des répertoires. isfile prend un nom de
chemin et retourne 1 si le chemin représente un fichier et 0 dans
le cas contraire. Ici, nous utilisons os.path.join
pour nous assurer que nous avons un nom de chemin complet, mais
isfile marche aussi avec des chemins
partiels, relatifs au répertoire en cours. Vous pouvez utiliser
os.getcwd() pour obtenir le répertoire en
cours.
os.path a aussi une
fonction isdir qui retourne 1 si le chemin
représente un répertoire et 0 dans le cas contraire. Vous pouvez
l’utiliser pour obtenir une liste des sous-répertoires d’un
répertoire.
Exemple 6.19. Liste des fichiers d’un répertoire dans fileinfo.py
def listDirectory(directory, fileExtList):
"get list of file info objects for files of particular extensions"
fileList = [os.path.normcase(f)
for f in os.listdir(directory)]
fileList = [os.path.join(directory, f)
for f in fileList
if os.path.splitext(f)[1] in fileExtList]
os.listdir(directory) retourne une liste
de tous les fichiers et répertoires de directory.
En parcourant la liste avec f, nous
utilisons os.path.normcase(f) pour normaliser
la casse en fonction des paramètres par défaut du système
d’exploitation. normcase est une petite
fonction utile qui compense le problème des systèmes
d’exploitation insensibles à la casse qui pensent que
mahadeva.mp3 et
mahadeva.MP3 sont le même fichier. Par
exemple, sous Windows et MacOS, normcase convertit
l’ensemble du nom de fichier en minuscules, sous les systèmes
compatibles UNIX, elle retourne le nom de
fichier inchangé.
En parcourant la liste normalisée avec f
à nouveau, nous utilisons os.path.splitext(f)
pour diviser chaque nom de fichier en nom et extension.
Pour chaque fichier, nous regardons si l’extension est dans
la liste d’extensions de fichier qui nous intéressent
(fileExtList, qui a été passé à la fonction
listDirectory).
Pour chaque fichier qui nous intéresse, nous utilisons
os.path.join(directory, f) pour construire le
chemin de fichier complet. Nous retournons une liste de noms de
chemin complets.
A chaque fois que c’est possible, vous devriez utiliser les
fonction de os et os.path pour les manipulations de
fichier, de répertoire et de chemin. Ces modules enveloppent des
modules spécifiques aux plateformes, les fonctions comme
os.path.split marchent donc sous
UNIX, Windows, MacOS et toute autre plateforme supportée par
Python.
Il existe une autre manière d'obtenir le contenu d'un répertoire. Elle est très puissante et utilise le type de jokers qui
vous sont familier si vous utilisez la ligne de commande.
Exemple 6.20. Liste du contenu d'un répertoire avec glob
Comme nous l'avons vu plus haut, os.listdir prend simplement un chemin de répertoire et retourne la liste de tous les fichiers et répertoires qu'il contient.
Le module glob, par contre, prend un joker et retourne le chemin complet de tous les fichiers et répertoires qui lui correspondent. Ici,
le joker est un chemin de répertoire plus "*.mp3", c'est à dire tous les fichiers .mp3. Notez que chaque élément de la liste retournée contient le chemin complet du fichier.
Voici le joker pour trouver tous les fichiers d'un répertoire qui commencent par "s" et finissent par ".mp3".
Maintenant considerez le scénario suivant : vous avez un répertoire music, contenant plusieurs sous-répertoires, avec des fichiers .mp3 dans chaque sous-répertoire. Vous pouvez obtenir une liste de tous ces fichiers avec un seul appel à glob, en utilisant deux jokers à la fois. Un des jokers est "*.mp3" (qui correspond aux fichiers .mp3) et l'autre est à l'intérieur du chemin de répertoire, ce qui correspond aux sous-répertoires de c:\music. C'est une énorme puissance contenue dans une fonction à l'air faussement simple !