Dans ce chapitre vous apprendrez à lire un fichier avec Python. Mais ce n'est pas tout ! Afin de bien commencer votre projet, vous apprendrez également à passer le nom de ce fichier en argument et à organiser votre projet de manière professionnelle.
Mais commençons par lire le CSV des membres !
Créez un dossier data
dans le dossier courant. Déplacez-y les fichiers que vous avez téléchargés au premier chapitre de ce cours.
current_mps.csv (le télécharger de nouveau)
SyceronBrut.xml (le télécharger de nouveau)
Organisation du projet
Les deux fichiers ont des fomats différents : CSV et XML. Afin de différencier les analyses, je vous propose de créer un script d'analyse par fichier :
csv_analysis.py
: analyse du fichiercurrent_mps.csv
xml_analysis.py
: analyse du fichierSyceronBrut.xml
Le fichier parite.py
, qui existe déjà, servira à lancer les analyses.
En récapitulant, voici l'organisation actuelle :
csv_analysis.py
parite.py
xml_analysis.py
data
current_mps.csv
SyceronBrut.xml
Parfait ! Ouvrez csv_analysis.py
et commençons à analyser le fichier CSV.
Analyse d'un fichier CSV
Nous allons utiliser la librairie standard os
afin d'interagir avec le système. Elle vous permet d'utiliser des fonctionnalités qui dépendent du système d'exploitation, par exemple écrire ou retrouver le chemin d'un fichier.
Importez-la en haut de votre fichier :
import os
Puis créez une fonction main()
, comme précédemment :
def main():
pass
if __name__ == "__main__":
main()
Lire un fichier
C'est très simple ! Utilisez la méthode open()
qui prend deux paramètres :
le chemin vers le fichier à lire
le mode d'ouverture (optionnel) :
r
ouvre un fichier en lecture,w
vous donne également le droit de le modifier, etc. En savoir plus
Comment indiquer le chemin vers un fichier à l'intérieur d'un script ? Encore une fois, Python vient à notre rescousse ! Vous pouvez utiliser la variable __file__
dont la valeur correspond au chemin vers un fichier. Puis nous pourrons retrouver très facilement le chemin du fichier que nous souhaitons utiliser. Voici comment faire :
csv_analysis.py
import os
def launch_analysis(data_file):
directory = os.path.dirname(__file__) # we get the right path.
path_to_file = os.path.join(directory, "data", data_file) # with this path, we go inside the folder `data` and get the file.
with open(path_to_file,"r") as f:
pass # read first line
if __name__ == "__main__":
launch_analysis('current_mps.csv')
Vous pouvez ensuite utiliser la méthode readline()
pour lire la première ligne du fichier. Démonstration :
def launch_analysis(data_file):
directory = os.path.dirname(__file__) # we get the right path.
path_to_file = os.path.join(directory, "data", data_file) # with this path, we go inside the folder `data` and get the file.
with open(path_to_file,"r") as f:
preview = f.readline()
print("Yeah! We managed to read the file. Here is a preview: {}".format(preview))
if __name__ == "__main__":
launch_analysis('current_mps.csv')
Voici ce qui apparait au lancement du fichier :
$ python csv_analysis.py id;nom;nom_de_famille;prenom;sexe;date_naissance;lieu_naissance;num_deptmt;nom_circo;num_circo;mandat_debut;groupe_sigle;parti_ratt_financier;sites_web;emails;adresses;anciens_mandats;autres_mandats;anciens_autres_mandats;profession;place_en_hemicycle;url_an;id_an;slug;url_nosdeputes;url_nosdeputes_api;nb_mandats;twitter;
Bravo ! Une première étape de franchie !
Vous pouvez à présent lire le fichier. Mais il serait plus intéressant de lancer l'analyse non pas à partir de ce fichier mais à partir de parite.py
afin de pouvoir choisir, plus tard, le format de fichier adéquat.
"Transformons" le fichier csv_analysis.py
en module.
Créer un module
Nous avons parlé des modules dans les quelques chapitres précédents mais nous ne les avons pas encore définis. Qu'est-ce qu'un module ?
Importer un module
Un module peut ensuite être importé de plusieurs manières. Celle que je préconise, et que j'utilise, est la suivante :
# Import du module
import csv_analysis as c_an
# Exécution de la fonction main() du module csv_analysis
c_an.main()
Modifiez donc les fichiers :
parite.py
import csv_analysis as c_an
if __name__ == '__main__':
c_an.launch_analysis('current_mps.csv')
csv_analysis.py
import os
def launch_analysis(data_file):
directory = os.path.dirname(__file__) # we get the right path.
path_to_file = os.path.join(directory, "data", data_file) # with this path, we go inside the folder `data` and get the file.
with open(path_to_file,"r") as f:
preview = f.readline()
print("Yeah! We managed to read the file. Here is a preview: {}".format(preview))
if __name__ == "__main__":
launch_analysis('current_mps.csv')
Vous avez réussi à lire le fichier csv. Bien joué !
Procédez de la même manière pour le fichier xml_analysis.py
même si nous le modifierons plus tard dans ce cours :
xml_analysis.py.
import os
def launch_analysis(data_file):
directory = os.path.dirname(__file__) # we get the right path.
path_to_file = os.path.join(directory, "data", data_file) # with this path, we go inside the folder `data` and get the file.
with open(path_to_file,"r") as f:
preview = f.readline()
print("Yeah! We managed to read the file. Here is a preview: {}".format(preview))
if __name__ == "__main__":
launch_analysis('SyceronBrut.xml')
parite.py
#! /usr/bin/env python3
# coding: utf-8
import csv_analysis as c_an
import xml_analysis as x_an
def main():
c_an.launch_analysis('current_mps.csv')
x_an.launch_analysis('SyceronBrut.xml')
if __name__ == "__main__":
main()
Importer une partie d'un module
Selon la taille d'un module, son import peut s'avérer très consommateur en mémoire. Lorsque vous travaillez avec des librairies conséquentes, telles que Pandas ou Numpy, il est d'usage de ne pas importer toute la librairie mais uniquement les objets dont vous aurez besoin.
Les imports personnalisés ont deux avantages majeurs :
Optimisation de la mémoire vive nécessaire à l'exécution du script.
Amélioration de la sécurité : plus vous importez de code, plus vous augmentez le risque que ce dernier soit frauduleux ou mal conçu.
csv_analysis.py
# remplace import os
from os import path
Pour importer plusieurs objets, séparez-les par des virgules :
from os import path, name
Créer une librairie
Simplifions notre projet en le transformant en librairie.
Qu'est-ce qu'une librairie ?
Une librairie, également appelée paquet (package en anglais), est un ensemble de modules. Cette organisation vous permet de les importer en utilisant une autre syntaxe en "point nomdumodule". Par exemple, un module qui s'appelle A.B désigne un sous-module appelé B dans un paquet s'appelant A.
Un paquet contient impérativement un fichier __init__.py
par module. Un dossier sans ce fichier ne sera pas reconnu comme étant un module du paquet.
Afin d'illustrer ce propos, voici ce que vous pourriez écrire dans le projet si vous le transformez en librairie :
import analysis.xml as x_an
import analysis.csv as c_an
Comment faire ?
Une librairie minimale est organisée de la façon suivante :
nom_librairie
setup.py
nom_sous_module
sous_module.py
__init__.py
Créez simplement un nouveau dossier, à la racine du projet, qui s'appelle analysis
. A l'intérieur, déplacez les fichiers xml_analysis.py
et csv_analysis.py
. Renommez-les xml.py
et csv.py
. Ajoutez également un fichier vide nommé __init__.py
dans analysis
.
rappel de l'organisation :
analysis
__init__.py
csv.py
xml.py
data
current_mps.csv
SyceronGlobal.xml
parite.py
setup.py
Mettez à jour parite.py
et relancez le programme. Vous devriez voir apparaître une erreur. C'est normal car les chemins d'accès aux fichiers ont changé ! Modifiez le fichier csv.py
:
def launch_analysis(data_file):
directory = os.path.dirname(os.path.dirname(__file__)) # we get the right path.
...
if __name__ == "__main__":
launch_analysis('SyceronBrut.xml')
Tout fonctionne comme prévu ! Faites-en de même pour xml.py
.
Lancer les fichiers en ligne de commande
A présent, concentrons-nous sur la résolution d'un souci : l'exécution de parite.py
lance deux analyses (xml et csv). Ce serait plutôt intéressant de choisir le type d'analyse.
Je vous propose de fournir cette indication en tant qu'argument lorsque vous lancez le script en ligne de commande. Ainsi :
$ python parite.py --extension xml
Utilisez pour cela la librairie standard Argparse. Elle contient de nombreuses méthodes très utiles pour récupérer des arguments.
Importez la librairie : import argparse
.
Nous allons l'utiliser en trois temps :
Création d'un objet
ArgumentParser()
Lecture des arguments
Renvoi des arguments
parite.py
import argparse
import analysis.csv as c_an
import analysis.xml as x_an
def parse_arguments():
parser = argparse.ArgumentParser()
parser.add_argument("-e", "--extension", help="""Type of file to analyse. Is it a CSV or an XML?""")
return parser.parse_args()
if __name__ == '__main__':
args = parse_arguments()
if args.extension == 'xml':
x_an.launch_analysis('SyceronBrut.xml')
elif args.extension == 'csv':
c_an.launch_analysis('current_mps.csv')
Exécutez la commande :
$ python parite.py -e csv Opening data file current_mps.csv from directory 'data' Yeah! We managed to read the file. Here is a preview: id;nom;nom_de_famille;prenom;sexe;date_naissance;lieu_naissance;num_deptmt;nom_circo;num_circo;mandat_debut;groupe_sigle;parti_ratt_financier;sites_web;emails;adresses;anciens_mandats;autres_mandats;anciens_autres_mandats;profession;place_en_hemicycle;url_an;id_an;slug;url_nosdeputes;url_nosdeputes_api;nb_mandats;twitter;
#! /usr/bin/env python3
# coding: utf-8
import argparse
import analysis.csv as c_an
import analysis.xml as x_an
def parse_arguments():
parser = argparse.ArgumentParser()
parser.add_argument("-e", "--extension", help="""Type of file to analyse. Is it a CSV or an XML?""")
parser.add_argument("-d","--datafile",help="""CSV file containing pieces of information about the members of parliament""")
return parser.parse_args()
def main():
args = parse_arguments()
datafile = args.datafile
if args.extension == 'xml':
x_an.launch_analysis(datafile)
elif args.extension == 'csv':
c_an.launch_analysis(datafile)
if __name__ == "__main__":
main()
A quoi sert le paramètre help
de la méthode add_argument()
?
Argparse vous donne la possibilité d'afficher un message expliquant les différents arguments en ajoutant -h
ou --help
.
Par exemple :
$ python parite.py --help
usage: parite.py [-h] [-d DATAFILE] [-e EXTENSION]
optional arguments:
-h, --help show this help message and exit
-d DATAFILE, --datafile DATAFILE
CSV file containing pieces of information about the
members of parliament
-e EXTENSION, --extension EXTENSION
Kind of file to analyse. Is it a CSV or an XML?
Découvrez toutes les fonctionnalités de la librairie dans la documentation.
Vous pouvez désormais lancer le programme en utilisant la commande suivante : python parite.py -d current_mps.csv -e csv
.
$ python parite.py -d current_mps.csv -e csv
Yeah! We managed to read the file. Here is a preview: id;nom;nom_de_famille;prenom;sexe;date_naissance;lieu_naissance;num_deptmt;nom_circo;num_circo;mandat_debut;groupe_sigle;parti_ratt_financier;sites_web;emails;adresses;anciens_mandats;autres_mandats;anciens_autres_mandats;profession;place_en_hemicycle;url_an;id_an;slug;url_nosdeputes;url_nosdeputes_api;nb_mandats;twitter;
Bravo ! Vous connaissez désormais la différence entre un module et une librairie. Vous savez également utiliser la librairie ArgParse
pour ajouter des arguments. Mais que se passe-t-il si vous indiquez un fichier qui n'existe pas ? Le programme renverra une erreur. Voyons dans le chapitre suivant comment les gérer.
A vous de jouer !
Code du chapitre
Retrouvez le code de ce chapitre en cliquant ici.