Aller au contenu

Import d'un fichier csv dans une liste de dictionnaire

Avec le module csv

On considère à nouveau le fichier temperatures_2020.csv. Ce fichier regroupe les températures minimales, maximales et moyennes dans différentes régions françaises pour certains jours de l'année 2020. Il est dans le dossier de travail et est encodé en utf-8.

Les premières lignes du fichier sont données ci-dessous :

📑 Données CSV
mois,jour,région,tmin,tmax,tmoy
août,13,Pays de la Loire,19.25,25.35,22.3
août,13,Occitanie,17.51,26.55,22.03
Repérer les bonnes informations

Observez l'extrait proposé et répondez aux questions suivantes :

  1. Quel est le séparateur utilisé ?
  2. Combien y-a-t-il de descripteurs ?
  3. Quels sont les types des descripteurs ? (entier, nombre décimal, chaîne de caractères...)
Solution
  1. Le séparateur est la virgule
  2. Il y a six descripteurs
  3. mois et région sont des chaînes de caractères, jour est un entier, les trois autres sont des flottants.

Le module csv de Python permet d'importer facilement des fichiers csv vers des listes de dictionnaires. La démarche est la suivante :

  • ouvrir le fichier csv,

  • créer un objet de typecsv.DictReader (voir plus bas),

  • l'utiliser pour lire les données du fichier et les convertir en dictionnaire.

Le code alors très concis :

Important

Prenez le temps de lire les commentaires !

Cliquez sur les +

import csv
with open("temperatures_2020.csv", "r", encoding="utf-8") as fichier:
    lecteur = csv.DictReader(fichier, delimiter=",")  # (1)
    temperatures = [entree for entree in lecteur]  # (2)
  1. Un objetcsv.DictReader prend deux arguments : le fichier à lire et le séparateur
  2. Les entree obtenues lors du parcours du lecteur sont des dictionnaires. On crée une liste en compréhension.
Comment Python connaît-il les descripteurs ?

Le comportement par défaut decsv.DictReader est de chercher les noms des descripteurs sur la première ligne du fichier. On utilise ce comportement ici.

Si la première ligne comprend des données et que les descripteurs ont été récupérés ailleurs, on peut les passer en argument (sous forme d'une liste par exemple) en faisantlecteur = csv.DictReader(fichier, delimiter=",", fieldnames=descripteurs)

Python < 3.8

Pour les versions précédentes de Python (avant la 3.8), il faut faire une conversion : temperatures.append(dict(entree))

Typage des données

Le modulecsv nous simplifie grandement la tâche mais il ne fait pas tout : les données ne sont pas typées :

temperatures = [
    {"mois": "août", "jour": "13", "région": "Pays de la Loire", "tmin": "19.25", "tmax": "25.35", "tmoy": "22.3"},
    {"mois": "août", "jour": "13", "région": "Occitanie", "tmin": "17.51", "tmax": "26.55", "tmoy": "22.03"},
    {"mois": "août", "jour": "14", "région": "Pays de la Loire", "tmin": "17.7", "tmax": "25.7", "tmoy": "21.7"},
    ...
]

Le typage s'apparente à celui effectué dans le cas d'une liste de listes. Il est néanmoins plus simple sur un point : on peut directement utiliser le nom des descripteurs plutôt que leurs indices.

Import et typage complets

Compléter le script ci-dessous permettant d'importer et de typer convenablement les données du fichier temperatures_2020.csv.

Ordre de lecture

Le test de validation compare votre liste avec la liste obtenue en lisant le fichier dans l'ordre des lignes (comme proposé partout dans ce cours).

Le test échouera donc si vous ne parcourez pas les lignes du fichier dans l'ordre...

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013,f]:gSa.xD3/9mocbPrhd_)witsy(25R4e-7k8 j[n6=puTv10l050v0I0A0h0z0Z0B0N0q0Z0h0B0B0S010A0z0T010406050B0U0o0o0h0t0C040g0p0Z0U0@0p0Q050m0~1012140|0T041d1k051n0m1n1p1k0|0v0z0W0,0.0:0=0u0z0f0u0Z1D0u0A0`050%0r0Z0I1y0/0;011C1E1G1E0A1M1O1K0A0r0p0v141L0t1l0A0u0,170B0T0h0Q0=0E011Q1A010c0)0I0Q0h0o0I1K1=1@1|1S1 1O22240`0a0N0s0t0p0T0p0B0z1a0Q0N0#1:0t0t0I0q2p1d270Q1l0m1.2C0A1,1+1-0v290=1G0Q212m1K1v1x0-1R2M0z2O0Q1(1w1K0T2v1l2A2C2*0}1?2q2U1}2Z0t110Z0`0N0X2z2.0{2-282:1S2=2@2_0E2|1@2~2A2L01330h2^040N0l372B0|3a310=3d3f0N0H3j392.3b3p2_0F3t3l3v3n3c0p2?3e2_0R3A2 2/1z323F343g0K3K3m3N3o3P3H3g0M3T3C3V3E3G3q0n3#303%3x040X0Y3,3M2V3(3Q0X2{1e2}3B3-3^3/0X363}383 3@2;3X3f0X3i452B1m2(1d2S2F0v2J3b0q1(251l4j1o4h2,4e1l4o0#2)3$3^0L0Q0`0z0o2l0t0A3t3L3b0y2_4L3U414E040q0B0W3A473b0L0`0y2o0u3t0N4M3D0Q0r0`2k214Q4B1}0_040D4?401}0B1`040?0I4H0I0t0h0A0U2v0B0w0E0Y5d0i4V0W014|481S4_0b4*4,3%4 0`010t5j4w5q3^5n5p4R2;0`214y2X0f5k3b0p0`0S5J3D5s51190c0J0M5w2,5C5m0`0x5B4@1S4#040/5$4}320`1 0q1C555O3%4_0e3A0N5|4+5Y3o0`1O2x0I595,5l0=5L045N4w5~5%604U4W5@3^690i6i5D040k0z2x0G0I0h0#0t6m5Z4`6x6f5:5=6w5x5 015A6c5y6n0#1G0o2o5?6F6e01696b5X6S5Q010b5W2}6K6y5#4w065}6d5-6f0A530T5557590I0B665K5M6{3D4_0P6A3c5E0Q2G0I0I6~3%5)0c3F79417476786J6G0p4O042X7e6n626:656R6.6H0`0d4Y4Z3D0q0X0`030N0V0C1?0f7i2*7A7a5/7d7j6S4T217h7p1S7l4F1c7R7v4T6:5456585a725_5{5}6%6f7U2v7L6$6G70726Y0O0p596#387;7w047y7#676T6}873w4/7n757-0`4{7u887T757@8g04718j3b7}7 5v8o0d6)7M6,838l7V8r6 0`8q6W7v6Y0A6O4E8w7W688a2*6-8k8d0c0Z0p578o8i8I8k7g8n8E5^8G7|500?8M814f7`7x8y3~8A6G8C8)8$3b7{8*3^8K110j8;4A7v4_868S836U8P3c8V8X8Z914^8h728|778o8H7_6X8.8L0h958w8^468`7S8(9o9j6y9q826G930p0C9683999e9d8b4-9g8Y4K9E0=4_8#9r7$9C7^9H6S908~5P9t0o9K9M8?859y3k1d4y0I2C2%9`4i1w4k2F2H2D1%1)2F0h1N9}0m4j0|aa0$0(0*04.
Remarque

La méthode proposée ici lit deux fois l'ensemble des informations :

  • une fois lors de l'import,
  • une fois lors du typage.

Il est possible de faire ces deux actions en une seule passe :

import csv

temperatures = []
with open("temperatures_2020.csv", "r", encoding="utf-8") as fichier:
    lecteur = csv.DictReader(fichier, delimiter=",")
    for entree in lecteur:
        entree["jour"] = int(entree["jour"])
        entree["tmin"] = float(entree["tmin"])
        entree["tmax"] = float(entree["tmax"])
        entree["tmoy"] = float(entree["tmoy"])
        temperatures.append(entree)

À la main !

Il est possible d'effectuer les mêmes actions sans utiliser le module csv. La démarche est un peu plus longue mais permet de bien comprendre le fonctionnement.

L'idée est la suivante :

  • ouvrir le fichier,
  • récupérer les noms des descripteurs à l'aide de la première ligne du fichier,
  • pour chaque ligne restant à lire :
    • la nettoyer et la découper,
    • créer un dictionnaire associant les noms des descripteurs aux valeurs,
    • ajouter ce dictionnaire à la liste générale.

Conseil

On pourra (re)lire avec intérêt la page sur les fichiers

Récupérer les noms des descripteurs

On considère un fichier csv dont le séparateur est la virgule.

Quelle(s) instruction(s) permet(tent) de récupérer les descripteurs ?

  • with open("fichier.csv", "r", encoding="utf-8") as fichier:
        for ligne in fichier:
            descripteurs = ligne.split(",")
    
  • with open("fichier.csv", "r", encoding="utf-8") as fichier:
        ligne = fichier.readline()
        ligne_propre = ligne.strip()
        descripteurs = ligne_propre.split(",")
    
  • with open("fichier.csv", "r", encoding="utf-8") as fichier:
        ligne = fichier.readline()
        descripteurs = ligne.strip().split(",")
    
  • with open("fichier.csv", "r", encoding="utf-8") as fichier:
        descripteurs = fichier.readline().strip().split(",")
    
  • ❌ On récupère ainsi les données de chaque ligne...
    with open("fichier.csv", "r", encoding="utf-8") as fichier:
        for ligne in fichier:
            descripteurs = ligne.split(",")
    
  • ✅ En trois temps :
    with open("fichier.csv", "r", encoding="utf-8") as fichier:
        ligne = fichier.readline()  # on lit la 1ère ligne
        ligne_propre = ligne.strip()  # on efface le \n
        descripteurs = ligne_propre.split(",")  # on découpe à chaque ","
    
  • ✅ En trois temps aussi mais sur deux lignes :
    with open("fichier.csv", "r", encoding="utf-8") as fichier:
        ligne = fichier.readline()  # lecture de la 1ère ligne
        descripteurs = ligne.strip().split(",")  # nettoyage et découpage
    
  • ✅ Tout en une seule ligne, ce n'est pas très clair !
    with open("fichier.csv", "r", encoding="utf-8") as fichier:
        descripteurs = fichier.readline().strip().split(",")
    
Import dans une liste de dictionnaires à la main

Compléter le script ci-dessous permettant d'importer les données du fichier temperatures_2020.csv dans une liste de dictionnaires. On n'utilisera pas le module csv.

Ordre de lecture

Le test de validation compare votre liste avec la liste obtenue en lisant le fichier dans l'ordre des lignes (comme proposé partout dans ce cours).

Le test échouera donc si vous ne parcourez pas les lignes du fichier dans l'ordre...

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013,f{]:gSa.3/9mocbPérhd_})wi;tsy(25Rq4e-7k8 [n6O=puv10l050v0L0C0i0A0#0D0Q0p0#0i0D0D0V010C0A0W010406050D0X0n0n0i0t0E040h0o0#0X0_0o0S0Q020i0n0W0B0Q0I0L130t0J0X0L0D050l101214160~0W041u1B051E0l1E1G1B0~0v0A0Y0.0:0=0@0u0A0g0u0#1U0u0C0|050)0q0#0L1P0;0?011T1V1X1V0C1%1)1#0C0q0o0v161$0t1C0C0u0.190D0W0i0S0@0G011+1R010c0+0L0S1h0L1#26282d1-2g1)2j0n2l040a0Q0r0t0o0W0o0D0A1c1e0%240t0t0L0p2G1u2n0S1C0l222S0C201 210v2p0@1X0S2i2D1#1M1O0/1,2$0A2(0S1|1N1#0W2L1C2Q2S2}0 271e2.2e2?0t130#0|0Q0Z2P310}302o331-3537390G3c283e2Q2#013j0i38040Q0k3n2R0~3q3h0@3t3v0Q0K3z3p313r3F390H3J3B3L3D3s0o363u390T3Q3f321Q3i3V3k3w0N3!3C3%3E3)3X3w0P3-3S3/3U3W3G0m3^3g3`3N040Z0!3 3$2/3{3*0Z3b1v3d3R4048420Z3m4d3o1D2{1u2,2V0v2Z3r0p1|2v0$1N1C2`0L2|3d3J054v0%4D4g340|0C1n0W0L0t0i0C0X2L1t4l2R0Q3#3r0o0|0V3J4Z3.480{040R0e463r0O0|0z2F0u4)4!3T0S0q0|2B2i4F4+2e4-0F533_4h0|2r0L584K1-4$044(4X4J472e0D2b040^4O4Q4S4U1s0w0G0!5y0j0p0D0Y015e5m1-4-0b4{543i0|0n4w5G4#4%5R3T5o0|010t5F5k4|3`5J5L594L042i4H2;0g5U3`5h5j2 5M0@5W5q1b0c0M0P5!5^5*5I0|0y5)5f0@4?040;675H3E5b0A0p1T4Q5;4,0|0f3Q0Q6q4*636f041;2(6d5S5i6y4}6g6i0A6k5#5_015h0j6l5+2L0i0v2%5d6H6t0156665k066r6s683s0|6w0L0w2`2B2L6B5=5T5k6#6e6%6v1U6x6T6$6K6M5N040D2W0`6 0@6W6p6r5$5a040%0D0p0t0`4N4U4W2}6?6z5@3d7m6C6_0g2(6+2A4B756J0|6L6|6@0S0|261X0C7y567y5{010b614E6I4-6X2}6Z796I6a0c3V6/7b6)7#2e0o0z0|2;7(702g6E6G626$4-6o6Y6!6!7a5+6)7v6-6S7l7}5g6;836I7E7s6{7?6@6~7C3M7F730W7J0|0F7T4e7{7W6U890Y3u0L7j7.0@5?8x6^7 6,7x8f3T8e8c8g710W7H8k04578F3`7M7O8N8n3o7V8p846u1M4v8A8z6=8Z6V0|0d0x788Y7X5b7!8)887,8%7+047-8@8r4 044R0S0g827Q6U7K8Q4h902s8N8P8I7r7d7f7h8v0t7k967@650y7_7U8p8:8r0|8#0o8N0R7y899h7g0W7i9l9z9B8_99550|0e4:8~6}867p8*8s8u8w9L644.9J8|8N9P9s9t9U4M5s4R4T4V7y8H9n7D0|0i0W4P0S0v9d9#9x8U3!0l4H4C4na50l4q1u0C4saa2X2T1{1}2V0i1(a74q1A5l3r2L0n0w0c0i0O6*0u0k0|1m1o1q1s0Q9r4E1H3e1B0U1e4P1b0Q0i0X0=0A0Q0C0E4P0t0.0t0s4Q0Q0X2H6h2G2j0A2L0Q2i241iaZ0u2i2E1daE1D3e2,3r1/1W1Y1!4A4o2 5#a4ao7r4N1i5t9/1s8%9S3o7q5%0|4/4;3T6a4^228A4~509{9~9Y6u5c9;bg2R8*7MbaaW5u4V5x5z0!5B5D7P4m7R0|5K9Q9@045P0%bz6Abw017M5Z8NbR879v5,0S5.93bX7obO6U7M5}5 bNbBbP048V4Y8*6a6cbS8J7:6j0t8NaF8W7|8^8a95bh8*8(b)6$89c46Fc6bZ9=b;ci0|6O6Q2;cdb`978lb}0}cab*8C7w6.c28GbA3w9+ccbX7B9f418h9E9dcz8Xbi7b9D9j9Xch8dcIcV7~6`6*8DcFcO48cocwcq8K8MbZ98c-5n5p7Nb_b8bjb|8/c%1-7Y8?c!8J7%cG5=8{8}d67rck7=9?3r7^d1cBc;cD81bfbYddcPcLcn7A9#72cRc@cydk8qc;8t1)cZ9T6IcgdHcCc)808Ec_8504cNdh7r7G2FbvdP5`c{8Tdzd07`9*cba0d9c.c$8*4-0d9 1s9i9F9k9mcp6@4-9AbZ890A9%c8b~cbdEd_9Id 9KdY8+049(dK6$d4cmdr7be1d,7)db0Sbr909294dXdT419b52d$9eevcWd?9E9Gd`c:d|9p8.d(9uc;bEbc5veGc~d-dR9#9_9{9}ez9 6h9yd$cT1ub7a62Sam4p0(0*0,04.