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.
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 python3en première ligne du script pour indiquer à l’interpréteur de commandes (shell) qu’il faut l’exécuter avec l’interpréteur mentionné (icipython3) ; - 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.
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 ;-)
TODO + carte mentale
- sys.exit
- sys.argv
- sys.stderr
- os.path.exists
- os.path.isdir
- os.path.isfile
- os.listdir
- os.path.join