Dossiers et chemins

Comment trouver efficacement un fichier dans le système de fichier de l'ordinateur.

Par défaut python va chercher les fichiers à ouvrir dans le dossier du fichier python en train d'être exécuté. On peut facilement chercher un fichier dans un dossier spécifique en python.

Commencez par intégrer la règle d'or :

On ne présuppose jamais de l'endroit où un fichier est stocké sur un ordinateur.

Supposons que vous ayez un fichier python dans le dossier /Users/fbrucker/Documents/mon_projet/main.py et que ce programme python utilise le fichier /Users/fbrucker/Documents/mon_projet/donnees.txt.

Si votre programme main.py utilise le fichier donnees.txt de cette façon :

donnees = open("/Users/fbrucker/Documents/mon_projet/donnees.txt").read()

Il ne pourra fonctionner que sur votre ordinateur ! En effet, si vous copiez le dossier "mon_projet" et tout son contenu de l'ordinateur A à l'ordinateur B, il est très peu probable qu'il soit placé au même endroit sur le disque dur.

Une première solution est d'utiliser un chemin relatif :

donnees = open("donnees.txt").read()

On voit que le chemin utilisé est relatif car il ne commence pas par un /. On cherche le fichier donnees.txt par rapport au dossier courant du terminal qui a exécuté le fichier python. De là, si vous êtes dans le dossier "mon_projet" lorsque vous tapez la commande python main.py votre programme marchera sur tous les ordinateurs.

Si cette technique fonctionne souvent, elle n'est cependant pas optimale car vous ne pouvez pas garantir que votre programme sera toujours exécuté depuis le dossier mon_projet/. S'il est par exemple exécuté depuis le parent de mon_projet/ : python mon_projet/main.py ; votre code ne fonctionnera plus puisque le dossier par défaut ne sera plus le bon...

La solution qui fonctionne tout le temps est de déterminer à l'exécution l'emplacement du fichier*"main.py"*. Ceci se fait grâce à la variable spéciale : __file__.

Copiez le code suivant dans un fichier et exécutez le pour voir le fonctionnement de la variable __file__ :

print(__file__)

On n'a fait que la moitié du chemin, puisque l'on a l'emplacement du fichier, mais pas le dossier. Ceci peut se faire en utilisant le module os.path de python :

Copiez le code suivant dans un fichier et exécutez le pour voir comment récupérer le dossier à partir de __file__ :

import os

print(__file__) # le chemin absolu jusqu'au fichier
print(os.path.dirname(__file__))  # le dossier
print(os.path.basename(__file__)) # le nom du fichier                                     

Cette méthode permet d'obtenir un chemin absolu de référence pour garantir l'accès aux fichiers de données sur toutes les machines où votre projet sera copié.

Un fois un dossier de référence trouvé, on pourra l'utiliser pour accéder à nos données. Mais jamais à la main :

Lorsque l'on manipule des fichiers ou que l'on combine des dossiers on utilise toujours une bibliothèque dédiée pour cela, on ne manipule jamais les noms de fichiers et de dossiers en utilisant des méthodes de chaînes de caractères

On va voir deux façons de faire en python, l'une classique avec le module os.path, l'autre plus moderne qui utilise le module pathlib.

Module os.path

On suppose que la variable __file__ corresponde au chemin /Users/fbrucker/Documents/mon_projet/main.py sur le disque dur. On suppose aussi que le module os a été importé.

Module pathlib

Le module pathlib permet d'avoir une approche objet de la manipulation des fichiers.

Ce tutoriel est parfait pour vous montrer comment l'utiliser.

Fichiers distants

Les fichiers stockés sur internet peuvent aussi être récupérés en python via leur url. On utilise la bibliothèque requests (python -m pip install requests).

Par exemple, le site https://www.gutenberg.org possède de nombreux livres au format utf-8 à télécharger. Par exemple https://www.gutenberg.org/ebooks/14155 :

import requests

page = requests.get("https://www.gutenberg.org/ebooks/14155.txt.utf-8")

Le code précédent à téléchargé le fichier contenu dans l'url https://www.gutenberg.org/ebooks/14155.txt.utf-8 dans la variable page.

Cette variable est un objet qui contient de nombreux attributs.

Le texte qui a été téléchargé, au format Unicode :

page.text

Un fichier téléchargé par internet l'a été octet par octet. Le type par défaut est donc le bytes et le contenu brut est disponible avec l'attribut content :

type(page.content)

La bibliothèque fait une conversion pour rendre l'attribut text au format Unicode.

La fonction requests.get va chercher le fichier sur internet. Donc utilisez cette fonction avec parcimonie car les accès réseau sont toujours lents par rapport aux fichiers sur le disque dur en local.

L'idéal esr de télécharger le fichier une fois, de le sauver sur votre disque dur puis d'utiliser ensuite tout le temps le fichier sauvegardé. Le code suivant regarde si un fichier donné existe (fonction os.path.exists), et sinon il le télécharge :

import os.path

import requests

URL = "https://www.gutenberg.org/ebooks/14155.txt.utf-8"
NOM_FICHIER_LOCAL = "madame_Bovary.txt"

texte = ""

if not os.path.exists(NOM_FICHIER_LOCAL):
    page = requests.get(URL)
    texte = page.text

    f = open(NOM_FICHIER_LOCAL, "w", encoding="utf-8")
    f.write(texte)
    f.close()
else:
    f = open(NOM_FICHIER_LOCAL, "r", encoding="utf-8")
    texte = f.read()
    f.close()