Aller au contenu

Dictionnaire modélisant le contenu d'un répertoire⚓︎

D'après 2022, Centres étrangers, J1, Ex. 3

Afin d'organiser les répertoires et les fichiers sur un disque dur, une structure arborescente est utilisée. Les fichiers sont dans des répertoires qui sont eux-mêmes dans d'autres répertoires, etc.

Dans une arborescence, chaque répertoire peut contenir des fichiers et des répertoires, qui sont identifiés par leur nom. Le contenu d'un répertoire est modélisé par la structure de données dictionnaire. Les clés de ce dictionnaire sont des chaines de caractères donnant le nom des fichiers et des répertoires contenus.

Un répertoire

Un répertoire est représenté par un dictionnaire dont chaque clé est :

  • soit un nom de sous répertoire : la valeur associée est alors un dictionnaire représentant le contenu de ce sous répertoire.
  • soit un nom de fichier : la valeur associée est alors un entier, représentant la taille du fichier en ko.

Un fichier est donc une clé d'un répertoire(dictionnaire) dont la valeur associée est un entier.

Exemple illustré

Le répertoire appelé Téléchargements contient deux fichiers rapport.pdf et jingle.mp3 ainsi qu'un répertoire Images contenant simplement le fichier logo.png.

Il est représenté ci-dessous.

%%{init: {'themeVariables': {'fontFamily': 'monospace'}}}%%
flowchart TB
    n0[[Téléchargements]] --> n1[[Images]]
    n1 --> n4(logo.png)
    n0 --> n2(rapport.pdf)
    n0 --> n3(jingle.mp3)

Ce répertoire Téléchargements est modélisé en Python par le dictionnaire suivant :

{"Images": {"logo.png": 36}, "rapport.pdf": 450, "jingle.mp3": 4800}

Les valeurs numériques sont exprimées en ko (kilo-octets).

"logo.png": 36 signifie que le fichier logo.png occupe un espace mémoire de 36 ko sur le disque dur.

On rappelle, ci-dessous, quelques commandes sur l'utilisation d'un dictionnaire :

  • dico = dict() crée un dictionnaire vide appelé dico,
  • dico[cle] = contenu met la valeur contenu pour la clé cle dans le dictionnaire dico,
  • dico[cle] renvoie la valeur associée à la clé cle dans le dictionnaire dico,
  • cle in dico renvoie un booléen indiquant si la clé cle est présente dans le dictionnaire dico.
  • for cle in dico: permet d'itérer sur les clés d'un dictionnaire.
  • len(dico) renvoie le nombre de clés d'un dictionnaire.

L'adresse d'un fichier ou d'un répertoire correspond au nom de tous les répertoires à parcourir depuis la racine afin d'accéder au fichier ou au répertoire. Cette adresse est modélisée en Python par la liste des noms de répertoire à parcourir pour y accéder.

Exemple : L'adresse du répertoire : /home/pierre/Documents/ est modélisée par la liste ["home", "pierre", "Documents"].

1. Dessiner l'arbre donné par le dictionnaire docs suivant, qui correspond au répertoire "Documents".

🐍 Script Python
docs = {
    "Administratif":{
        "certificat_JDC.pdf": 1500,
        "attestation_recensement.pdf": 850
    },
    "Cours": {
        "NSI": {
            "TP.html": 60,
            "dm.odt": 345
        },
        "Philo": {
            "Tractatus_logico-philosophicus.epub": 2600
        }
    },
    "liste_de_courses.txt": 24
}
Réponse
%%{init: {'themeVariables': {'fontFamily': 'monospace'}}}%%
flowchart TB
    doc[[Documents]] --> adm[[Administratif]]
    adm --> certif(certificat_JDC.pdf)
    adm --> attest(attestation_recensement.pdf)

    doc --> cours[[Cours]]
    cours --> nsi[[NSI]]
    nsi --> tp(TP.html)
    nsi --> dm(dm.odt)

    cours --> philo[[Philo]]
    philo --> tlp(Tractatus_logico-philosophicus.epub)

    doc --> lst(liste_de_courses.txt)

2. On donne la fonction parcourt suivante qui prend en paramètres un répertoire racine et une liste représentant une adresse, et qui renvoie le contenu du répertoire cible correspondant à l'adresse.

Exemple : Si la variable docs contient le dictionnaire de l'exemple de la question 1 alors parcourt(docs, ["Cours", "Philo"]) renvoie le dictionnaire {"Tractatus_logico-philosophicus.epub": 2600}.

2.a. Recopier et compléter la ligne 4

🐍 Script Python
def parcourt(racine, adr):
    repertoire = racine
    for nom_repertoire in adr:
        repertoire = ...
    return repertoire
Réponse
🐍 Script Python
def parcourt(racine, adr):
    repertoire = racine
    for nom_repertoire in adr:
        repertoire = repertoire[nom_repertoire]
    return repertoire

2.b. Soit la fonction suivante :

🐍 Script Python
def affiche(racine, adr, nom_fichier):
    repertoire = parcourt(racine, adr)
    print(repertoire[nom_fichier])

Qu'affiche l'instruction affiche(docs, ["Cours", "NSI"], "TP.html") sachant que la variable docs contient le dictionnaire de la question 1 ?

Réponse
  • La première instruction fait que repertoire correspond au dictionnaire "NSI" qui vaut {"TP.html": 60, "dm.odt": 345}.
  • La seconde affiche la valeur associée à la clé "TP.html" de ce dictionnaire, c'est-à-dire le poids en ko de ce fichier.

L'affichage est donc

🐍 Console Python
>>> affiche(docs, ["Cours", "NSI"], "TP.html")
60

3.a. La fonction ajoute_fichier suivante, de paramètres racine, adr, nom_fichier et taille, ajoute au dictionnaire racine, à l'adresse adr, la clé nom_fichier associé à la valeur taille.

Une ligne de la fonction donnée ci-dessous contient une erreur. Laquelle ? Proposer une correction.

🐍 Script Python
def ajoute_fichier(racine, adr, nom_fichier, taille):
    repertoire = parcourt(racine, adr)
    taille = repertoire[nom_fichier]
Réponse
🐍 Script Python
def ajoute_fichier(racine, adr, nom_fichier, taille):
    repertoire = parcourt(racine, adr)
    repertoire[nom_fichier] = taille

3.b. Écrire une fonction ajoute_repertoire de paramètres racine, adr et nom_repertoire qui crée un dictionnaire représentant un répertoire vide appelé nom_repertoire dans le dictionnaire racine à l'adresse adr.

Réponse
🐍 Script Python
def ajoute_repertoire(racine, adr, nom_repertoire):
    repertoire = parcourt(racine, adr)
    repertoire[nom_repertoire] = dict()

4.a.

isinstance pour vérifier le type d'une variable

isinstance(variable, A) renvoie True si variable est de type A et False sinon.

A peut être le type int, dict ou tout autre type Python.

Écrire une fonction est_fichier de paramètres repertoire et cle, où cle est une clé du dictionnaire repertoire, qui détermine si cle correspond à un fichier ou non. Si cle n'est pas une clé de repertoire, la fonction doit provoquer une erreur.

On pourra compléter le code suivant ou en proposer un autre

🐍 Script Python
def est_fichier(repertoire, cle):
    return ...
Réponse

Une version simple est

🐍 Script Python
def est_fichier(repertoire, cle):
    return isinstance(repertoire[cle], int)

Pour choisir le message d'erreur, on peut écrire

🐍 Script Python
def est_fichier(repertoire, cle):
    if cle in repertoire:
        return isinstance(repertoire[cle], int)
    else:
        raise KeyError("cle n'est pas une clé de repertoire")

4.b Écrire une fonction taille de paramètre racine qui prend en paramètre un dictionnaire racine modélisant un répertoire et qui renvoie le total d'espace mémoire occupé par les fichiers contenus dans ce répertoire et ceux qu'il contient, de manière récursive.

Réponse
🐍 Script Python
def taille(racine):
    cumul = 0
    for cle in racine:
        if est_fichier(racine, cle):
            cumul += racine[cle]
        else:
            cumul += taille(racine[cle])
    return cumul