Mini-cours de Python

CLI - Command line interface

Ces exemples n'ont pas pour but de vous donner une solution de qualité professionnelle (prête à l'emploi), mais de vous donner un aperçu de l'intérêt à créer ses propres outils.

Interface = nom donné au mécanisme qui permet à un humain de communiquer avec un ordinateur.

Il existe deux types d'interface : CLI et GUI

L'interface en ligne de commande (en anglais, command line interface, en abrégé CLI) est très sobre (en noir et blanc). Un outil qui ne permet pas de cliquer est appelé : Programme. La souris peut néanmoins être utilisée pour le copier/coller (pas pour cliquer).

L'interface graphique pour utilisateur (en anglais, graphical user interface, en abrégé GUI). Un outil qui permet de cliquer est appelé : Logiciel. De plus, les logiciels utilisent des composants (, , ...) comme sur certaines pages web et des couleurs ...

Pour l'utilisateur, le logiciel est plus agréable que le programme. Toutefois, d'une part, pour un même travail, le programme va plus vite que le logiciel (car, il ne doit pas s'occuper, en plus, de la partie "agréable"). Et, d'autre part, pour le développeur, le code est moins long et moins complexe.

Commençons par ce qui est moins complexe.

Copie filtrée d'un fichier texte

Dans ce code, les lignes débutant par # ne seront pas recopiées :

CC="fichier.txt"

f=open(CC)
f2=open("from_"+CC,"a")

lines = f.readlines()
for line in lines:
  if not line.startswith("#"): f2.write(line)

f.close
f2.close

print("Recopiage partiel terminé")

Ce code requiert 4 pré-requis :

  1. Le programme est dans le même dossier que le fichier à recopier
  2. Le fichier à recopier, "fichier.txt", existe
  3. Ce fichier dispose d'une ligne débutant par le caractère (#)
  4. Le fichier "from_fichier.txt" n'existe pas. (S'il existe, il sera complété)

Ce programme ne demande rien à l'utilisateur. Il suffit de le lancer. Il fait le travail. Sa dernière instruction est d'afficher un message pour avertir l'utilisateur qu'il a fini.

Fichier CSV

Supposons qu'une banque vous offre la possibilité de télécharger un fichier CSV contenant toutes vos opérations mensuelles et que vous souhaitez connaître le montant total des opérations liées à un compte tiers.

Si votre banque ne vous offre pas l'outil nécessaire (ou seulement à ses clients aisés), vous devrez créer cet outil vous-même.

Ci-dessous un exemple de code :

CC=input("Nom du fichier CSV : "); f=open(CC)
carac=";"; numColIbanTiers=5; ibanTiers=input("Numéro du compte tiers à totaliser : ")
numColMontant=3; total_positif=0.0; total_negatif=0.0
for ligne in f:
  liste=ligne.split(carac)
  if liste[numColIbanTiers]==ibanTiers:
    if float(liste[numColMontant])>0:
      total_positif+=float(liste[numColMontant])
    else: total_negatif+=float(liste[numColMontant])
f.close
print("Total positif : "+str(total_positif))
print("Total négatif : "+str(total_negatif))
print("Solde         : "+str(total_positif-total_negatif))

Le code ci-dessus fonctionne. Toutefois, il n'est pas souple car il ne s'adapte pas au fichier CSV fourni par une autre banque ...

Écrivons le code d'un programme adapté à toute banque et permettant d'enregistrer le résultat dans un fichier.

# Ce programme analyse le contenu d'un fichier CSV contenant toutes les opérations mensuelles.
# Chaque ligne du fichier représente une opération.
# Le point décimal est utilisé dans les montants

# Conseil 1 : Placer tous les fichiers CSV du même type dans un dossier. Par exemple, banque/
# Conseil 2 : Renommer les fichiers CSV fournis par AAAA-MM.csv. Par exemple, 2020-12.csv
# Conseil 3 : Placer le présent programme dans le dossier des fichiers CSV

CC=""
while len(CC) < 1:
  CC=input("Nom du fichier CSV : ")
  if CC=="":CC="2019-04.csv"   # valeur par défaut

f=open(CC)            # ouvre le fichier (en lecture)

# À ce stade, le fichier existe (ou un message d'erreur s'est affiché)
carac=""
while len(carac) < 1:
  carac=input("Caractère séparateur dans ce fichier CSV : ")
  if carac=="":carac=";"   # valeur par défaut

numColIbanTiers=-1
while numColIbanTiers < 0:
  x=input("Numéro de la colonne des numéro de compte tiers [0-n] : ")
  if x=="":numColIbanTiers=5   # valeur par défaut
  else:numColIbanTiers=int(x)  # peut provoquer une erreur si x ne représente pas un nombre

ibanTiers=""
while len(ibanTiers) < 1:
  ibanTiers=input("Numéro du compte tiers à totaliser : ")
  #if ibanTiers=="":ibanTiers="BExxxxxxxxxx"   # valeur par défaut

numColMontant=-1
while numColMontant < 0:
  x=input("Numéro de la colonne à totaliser [0-n] : ")
  if x=="":numColMontant=3    # valeur par défaut
  else: numColMontant=int(x)  # peut provoquer une erreur si x ne représente pas un nombre

total_positif=0.0
total_negatif=0.0       # un nom de variable ne peut pas contenir de caractère accentué

# Analyse du fichier, ligne par ligne
for ligne in f:
  liste=ligne.split(carac)
  if liste[numColIbanTiers]==ibanTiers:
    if float(liste[numColMontant])>0:
      total_positif+=float(liste[numColMontant])
    else: total_negatif+=float(liste[numColMontant])
f.close               # ferme le fichier CSV

print("")
print("Total positif : "+str(total_positif))
print("Total négatif : "+str(total_negatif))
print("Solde         : "+str(total_positif-total_negatif))
print("")

toSave=False
re=input("Enregistrer le résultat ? (y/N) : ")  # valeur par défaut en MAJUSCULE
if re=="y":toSave=True

if toSave:
  nomFichier=input("Nom du fichier : ")
  f=open(nomFichier,"w")        # ouvre le fichier (en mode "écrasement")
  f.write("Nom du fichier analysé   : "+CC+"\n")
  f.write("Numéro du compte analysé : "+ibanTiers+"\n")
  f.write("Total positif : "+str(total_positif)+"\n")
  f.write("Total négatif : "+str(total_negatif)+"\n")
  f.write("Solde         : "+str(total_positif-total_negatif)+"\n")
  f.close               # ferme le fichier
  print("Résultat enregistré.")

print("--- Bonne journée. --- Fin du programme.")   # envoi d'ondes positives au cerveau
print()
# Fin du programme

On constate que le coeur du programme est exactement le même. Mais, le programme offre plus d'options à l'utilisateur, tout en gardant les valeurs par défaut (pour une banque). Toutefois, à la moindre erreur, le programme plante.

Il vous appartient donc de corriger ce code.

On constate aussi que plus le programme est souple, plus il offre de possibilités, plus il contrôle les données fournies par l'utilisateur, ... Bref, plus le programme est agréable pour l'utilisateur, plus le code est long ...

Aperçu. Les résultats sont identiques pour les deux programmes.

Contenu du fichier contenant les résultats :

Nom du fichier analysé   : xxx.csv
Numéro du compte analysé : BE79679200211333
Total positif : 251.82
Total négatif : 0.0
Solde         : 251.82

Base de données

Supposons que vous disposiez d'un dossier rempli de photos et que vous souhaitez retrouver une photo, via des mots clés.

Si le logiciel dédié n'est pas livré avec votre appareil photo ou que vous n'en achetez pas, vous devrez créer l'outil vous-même.

Ici, le programmeur doit avoir, préalablement, des connaissances en SQL, SQLite et sur le module sqlite3.

Pour plus de lisibilité, nous allons créer plusieurs petits programmes remplissant une tâche spécifique.

Commençons par créer la base de données :

import sqlite3

con = sqlite3.connect('mesPhotos.db')   # nom du fichier qui sera créé
cur = con.cursor()

cur.execute('''CREATE TABLE jpg         # création de la structure de la base de données
(id INTEGER PRIMARY KEY AUTOINCREMENT,
nomFichier TEXT NOT NULL UNIQUE,
description TEXT);''')

con.commit()
con.close()

La base de données sera créée dans le dossier contenant ce programme.

Créons un programme pour remplir la base de données avec le nom de tous les fichier *.jpg du dossier (contenant ce programme). À chaque fichier, l'utilisateur sera invité à fournir un ou plusieurs mots-clés (séparés par un espace).

import sqlite3
import os

CC=""
while len(CC) < 1:
  CC=input("Nom du fichier .db : ")  # La base de données doit avoir la bonne structure
  if CC=="":CC="mesPhotos.db"        # nom par défaut

con = sqlite3.connect(CC)
cur = con.cursor()

path="."        # = emplacement du dossier courant (= contenant le présent programme)
#path="./tmp"   # = sous-dossier /tmp par rapport au dossier courant
# Si le sous-dossier /tmp n'existe pas, un message d'erreur s'affichera.

# Pour chaque fichier ayant l'extension ".jpg"
for file in os.listdir(path):
    if file.endswith(".jpg"):
      description=input("Description du fichier "+file+" : ")
      description=description.replace('"','')  # " est un caractère interdit
      cur.execute("INSERT INTO jpg VALUES (NULL,'"+file+"','"+description+"');")

con.commit()
con.close()

Tel que codé, si le dossier contient de nombreux fichiers .jpg, il faudra leur donner à tous une description. Ce qui peut prendre du temps. Ce programme devra donc être amélioré pour pouvoir poursuivre un remplissage interrompu. Un autre, pour modifier les descriptions. Un autre, pour mettre mettre à jour la base de données en fonction de l'ajout ou de la suppression de photos dans le dossier, voire lorsque le fichier a été renommé.

Enfin, créons un programme pour afficher le nom des fichiers correspondant à un mot-clé :

import sqlite3
import os.path

BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # dossier du programme

CC=""
while len(CC) < 1:
  CC=input("Nom du fichier .db : ")  # La base de données doit avoir la bonne structure
  if CC=="": CC = os.path.join(BASE_DIR, "mesPhotos.db")        # nom par défaut
  else:      CC = os.path.join(BASE_DIR, CC)

con = sqlite3.connect(CC)
cur = con.cursor()

print("Tapez 'EndProgram' comme mot-clé pour quitter ce programme\n")

mot_cle=""
while mot_cle!="EndProgram":
  mot_cle=input("Mot-clé : ")
  mot_cle=mot_cle.replace('"','')  # " est un caractère interdit
  cur.execute("SELECT nomFichier FROM jpg WHERE description like \"%"+mot_cle+"%\";")
  print(cur.fetchall())

con.commit()
con.close()

La méthode .fetchone() retourne un 'None' ou une ligne sous la forme d'un 'tuple'. Tel que ('movie',)

La méthode .fetchall()retourne un 'None' ou un tableau sous la forme d'une 'list' de 'tuple'.

D'autres programme

Développer un programme peut prendre des jours, des semaines, ...

Marre de l'interface noire ? Optez pour les interfaces graphiques.