Introduction

Un programme doit pouvoir interagir avec le système d’exploitation : fichiers, (et bases de données), périphériques, processus, réseau… Ce cours introduit la programmation système :

  • arguments d’un programme,
  • système de fichiers,
  • lecture et l’écriture de fichiers binaires.

Arguments d’un programme

Comme pour les fonctions, les arguments d’un programme sont ses paramètres d’entrée pour adapter son comportement sans modifier son code. En Python, ils sont accessibles dans la variable sys.argv (module sys à importer) qui est de type List (tableau).

Les arguments peuvent notamment être des chemins de fichiers.

Exemple

import sys

if __name__ == "__main__":
    print("'sys.argv' est un tableau : " + str(sys.argv), end="\n\n")

    print("sys.argv[0] = " + sys.argv[0] + " - c'est toujours le programme")
    for i in range(1, len(sys.argv)):
        print("sys.argv[" + str(i) + "] = " + sys.argv[i])

Exécuter ce programme : python3 script.py essai "autre chose" …

Erreurs et codes de sortie

Habituellement, lorsqu’un programme attend des arguments (paramètres), une des premières choses à faire est de vérifier le nombre d’arguments attendus :

import sys

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("usage : " + sys.argv[0] + " argument_attendu", file=sys.stderr)
        sys.exit(1) #toute valeur de sortie ≠ 0 indique une erreur

C’est une bonne pratique d’émettre le message d’erreur vers stderr (standard error — 2 dans le shell) plutôt que vers la sortie par défaut stdout (standard output). Ils peuvent ainsi être masqués ou redirigés vers un journal d’erreur ; exemple :

python3 script.py 2> /dev/null
python3 script.py 2> error.log
cat error.log

Si les arguments sont obligatoires, il est recommandé — pour faciliter son intégration avec d’autres outils — de quitter le programme avec un code d’erreur, c’est à dire un nombre différent de 0 (succès) : 1, 2… exemple :

python3 script.py toto
code=$?             #récupère le code de retour du programme
if (( $code != 0 )); then
    bold=$(tput bold)
    normal=$(tput sgr0)
    echo -e "\n${bold}erreur : le programme a renvoyé ${code}${normal}"
fi

Exécution directe

Un programme en Python (ou dans un autre langage) peut-être exécuté sans invoquer l’interpréteur sur la ligne de commande ; cf ./script.py … par exemple. Pour cela, il faut :

  • ajouter #!/usr/bin/env python3 en première ligne du script pour indiquer à l’interpréteur de commandes (shell) qu’il faut l’exécuter avec l’interpréteur mentionné (ici python3) ;
  • rendre le script exécutable chmod u+x script.py.

Remarque : pour des raisons de sécurité, le système peut interdire d’exécuter des programmes présents sur une clé USB, sur un point de montage en réseau ou encore dans le répertoire personnel de l’utilisateur.

Système de fichiers

Un programme peut accéder au système de fichier : parcourir un dossier, vérifier si un fichier existe, renommer ou supprimer des fichiers… Cf module os de Python.

Vérifier si un fichier ou dossier existe

#!/usr/bin/env python3

import os
import sys

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("erreur : argument manquant", file=sys.stderr)
        print("usage : " + sys.argv[0] + " chemin/dossier", file=sys.stderr)
        sys.exit(1)

    chemin = sys.argv[1]

    if not os.path.exists(chemin): #fonctionne avec fichiers ou dossiers
        print("erreur : " + chemin + " n'existe pas", file=sys.stderr)
        sys.exit(2)

    if not os.path.isdir(chemin): #isfile pour un fichier
        print("erreur : " + chemin + " n'est pas un dossier", file=sys.stderr)
        sys.exit(2)

    print("ok : " + chemin + " existe et est un dossier")

*Rappel : “dir” siginifie “directory” (répertoire) ; c’est un synonyme de “folder” (dossier).

Remarque : dans cet exemple, des codes d’erreur différents sont utilisés : 1 pour paramètre(s) manquant(s), 2 pour fichier(s) / dossier(s) inexistant… c’est une bonne pratique, mais le choix est libre.

Lister un dossier

#!/usr/bin/env python3

import os
import sys

if __name__ == "__main__":
    if len(sys.argv) != 2 or not os.path.isdir(sys.argv[1]):
        print("usage : " + sys.argv[0] + " dossier", file=sys.stderr)
        sys.exit(1 if len(sys.argv) != 2 else 2)

    folder = sys.argv[1]
    print("contenu du dossier " + folder + " : " + str(os.listdir(folder)))
    for name in os.listdir(folder):
        path = os.path.join(folder, name)
        if os.path.isfile(path):
            print(path)
        else:
            print(path + "/") #pour faire joli ;-)

Lecture et écriture de fichiers binaires

TODO + carte mentale

Synthèse

  • sys.exit
  • sys.argv
  • sys.stderr
  • os.path.exists
  • os.path.isdir
  • os.path.isfile
  • os.listdir
  • os.path.join