PYTHON : Initiation
Ce mois-ci je propose une petite initiation au langage Python. Le but ici n'est pas de produire un tutoriel exhaustif, déjà très nombreux sur le WEB, mais de donner envie d'utiliser ce langage moderne.
La première version de Python est sortie en 1991. La version 2 date de 2000, la version 3 de 2008. C'est à l'heure actuelle un des langages les plus utilisés, aussi bien sur PC que sur plateforme embarquée. Pour ma part, Python représente une grande part des lignes de code que j'ai écrites aussi bien dans ma vie privée que professionnelle.
Python peut être utilisé pour une grande variété de projets :
- automatisation
- projets scientifiques
- serveurs WEB
- bases de données
- communication
- interface graphique
- etc.
Sus ce blog il suffit de rechercher le mot "python" pour constater que j'ai déjà publié pas mal de petits scripts.
1. Cibles
Les plateformes sur lesquelles peut tourner Python sont nombreuses :
- machine Windows, MacOs, Linux
- cartes SBC comme la Raspberry PI, BeagleBone, Banana PI
Mais il existe aussi des versions de Python légères, comme MicroPython, qui peuvent se contenter de plateformes moins puissantes comme les ESP32, STM32.
Le principal intérêt de Python sur des plateformes aussi variées est la portabilité et on comprend vite l'intérêt d'utiliser un langage unique : limiter la formation.
A l'heure actuelle je développe essentiellement avec :
- sur PC : Python, HTML, JavaScript
- sur RASPBERRY PI : Python, HTML, JavaScript
- sur ESP8266, ESP32, ARDUINO : C, C++, HTML, JavaScript
2. Installation
L'installation de Python est simple.
Sous Linux, en fonction de la distribution, il est souvent pré-installé. Pour le vérifier, lancer la commande suivante :
python -V
S'il est installé il va afficher sa version :
Python 3.12.3
Si ce n'est pas le cas, il faut utiliser la méthode d'installation de la distribution :
Sous Ubuntu : sudo apt-get install python
Sous Fedora : sudo dnf install python3
Sous Windows il faudra télécharger le logiciel d'installation ici.
Sous Windows n'oubliez pas de cocher la case "Add Python 3.XX to PATH" :
2.1. Installation de packages
Installer le langage Python ne veut pas dire que l'on installe simplement un interpréteur nu avec des instructions basiques. Un nombre très important de librairies sont présentes : The Python Standard Library
Par contre d'autres librairies peuvent vous apporter des fonctionnalités avancées. Par exemple, on peut très bien développer un serveur WEB à l'aide du package http.server, présent dans la librairie standard, mais c'est un peu comme travailler avec un marteau et une enclume. Pour développer des application plus cossues, on a souvent recours à des frameworks comme Jango, ou CherryPy.
2.2. Pip
Certains sites proposent l'installation de leurs packages à l'aide de pip (Package Installer for Python).
C'est en effet un procédé très simple, qui permet d'installer des packages sans avoir à télécharger une archive et se préoccuper de l'endroit où il va falloir la décompresser.
Sous Ubuntu ou Debian : sudo apt install python3-pip
Sous Windows : Comment installer PIP sur Windows
On pourra ainsi installer par exemple le package de communication série PySerial comme ceci :
pip install pyserial
3. La console
Python met à votre disposition une console qui vous permettra d'exécuter du code sans avoir à créer de fichier source :
Il suffit pour cela de taper la commande python dans un terminal :
python
ou (sous Windows)
py
Python 3.12.3 (main, Nov 6 2025, 13:44:16) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Ensuite on entre le code à exécuter :
On quitte la console en tapant CTRL-D.
Cette console est un moyen très pratique de taper quelques lignes de code rapidement pour faire des essais.
4. Un tutoriel ?
Il existe énormément de tutoriels sur le langage Python. Je vous propose le tutoriel officiel pour démarrer.
Celui de W3school, en anglais, aborde des sujets supplémentaires :
- mathplotlib
- fichiers
- base de données MySQL
- etc.
Attention : il est assez déconseillé d'adopter de vieux tutoriels Python2 pour travailler en Python3, car les différences sont assez importantes.
5. Quel éditeur ?
Pour écrire du code, on utilise un éditeur de texte. Certains éditeurs évolués comme Visual Studio Code vous apporteront un certain confort, en particulier la coloration syntaxique.
L'écriture de code en Python n'utilise pas d'accolades pour définir les blocs de code comme en C ou C++, mais une indentation.
En C, on utilise des accolades :
for (i=0 ; i < 4 ; i++)
{
printf("blabla\n");
printf("%d\n", i);
}
L'équivalent en Python :
for i in range(4):
print("blabla")
print(i)
Ce code produira le résultat suivant :
blabla
0
blabla
1
blabla
2
blabla
3
Mais si vous écrivez :
for i in range(4):
print("blabla")
print(i)
Ce code produira le résultat suivant :
blabla
blabla
blabla
blabla
3
Attention donc.
Pour l'indentation il va falloir faire un choix. Soit vous utilisez la tabulation, soit vous utilisez des espaces. La majeure partie des éditeurs modernes permettent d'insérer des espaces lorsque l'on insère une tabulation. En général, la taille d'une tabulation est configurable. Un nombre de 3 ou 4 espaces est en général une bonne valeur.
6. Domaines d'application
Les domaines d'application sont très nombreux. Je n'ai pas l'intention de tous les énumérer, mais en voici quelques exemples :
6.1. Instructions de base
Quand on débute en Python, on constate assez vite que la simplicité est au rendez-vous. De plus, Python emprunte au langage C certaines caractéristiques essentielles, mais aussi à JavaScript :
Commentaire :
# comment
Commentaire sur plusieurs lignes :
'''
comment using string literals
with triple quotes
'''
Déclaration d'un entier :
a = 100
Déclaration d'un entier en notation hexadécimale :
a = 0x44
Déclaration d'un caractère en notation hexadécimale :
a = "\x44"
Déclaration d'une chaîne de caractères :
s = "this is a string"
s = 'this is a string'
a = "\x44\x33"
On peut accéder à un caractère particulier dans la chaîne, comme en C :
t = "string"
print(t[2])
Les tableaux :
On remarque deux types de tableaux : le premier, appelé liste, modifiable (entre crochets), le deuxième, appelé tuple, non modifiable (entre parenthèses).
Tous les tableaux sont indexés en partant de ZÉRO, comme en C.
En Python on peut ajouter, modifier ou supprimer un élément de liste :
t = [0, 1, 2, 3]
t.append(5) # ajoute un élément dont la valeur est 5
t[4] = 12 # modifie l'élément 4
t.pop(2) # retire l'élément 2
Au final, le contenu sera : [0, 1, 3, 12]
Appel de fonction ou de méthode :
function(arguments)
object.method(arguments)
Un dictionnaire, que l'on peut assimiler à une structure C :
x = {"name" : "John", "age" : 36}
Les habitués du C ou de JavaScript ne seront donc pas complètement perdus.
On remarque que le type des variables n'est pas explicitement déclaré.
On peut parfaitement écrire :
a = 100
a = "abcdef"
La variable a change donc de type à volonté. C'est un point qui m'a fortement perturbé à mes débuts. On m'a répondu "simple question d'ouverture d'esprit". J'ai donc arrêté de me plaindre et me suis accroché.
En fait chaque fonction est libre de contrôler ses arguments :
range("3")
Produit une exception :
TypeError: 'str' object cannot be interpreted as an integer
6.1.1. Boucle for
En C on écrirait :
for (i=0 ; i < 4 ; i++)
{
printf("i a pour valeur %d\n", i);
}
L'équivalent en Python :
for i in range(4):
print("i a pour valeur", i)
Dans cet exemple les différences sont flagrantes :
- pas d'accolades mais une simple indentation (tabulations ou espaces)
- pas de point-virgule
6.1.2. Séquence
On l'aura compris, la fonction range() retourne une séquence de nombres, 0 à 4 dans l'exemple précédent.
range() peut prendre 3 arguments :
range(3, 10, 2) # retourne une séquence de 3 to 9, par pas de deux : [3, 5, 7, 9]
Si on désire une séquence sans logique précise, on peut l'écrire comme ceci :
for i in [0, 2, 4, 8, 13]:
print("i a pour valeur", i)
[0, 2, 4, 8, 13] est aussi une séquence. On remarque déjà qu'en C ou C++ il serait plus difficile d'écrire l'équivalent.
c = ["Un", "problème", "sans", "solution", "est", "un", "problème", "mal", "posé"]
for i in range(len(c)):
print("i vaut", i, "et c[i] vaut", c[i])
6.1.3. Typage
Dans les exemples précédents on a vu que [0, 2, 4, 8, 13] et ["Un", "problème", "sans", "solution", "est", "un", "problème", "mal", "posé"] sont des séquences.
Peut on mélanger les chaînes de caractères et les nombres dans une séquence ?
c = [1, "problème", "sans", "solution", "est", 1, "problème", "mal", "posé"]
Oui. Cette déclaration est tout à fait valide.
Il est même possible de déterminer le type de chaque élément :
c = [1, "problème", "sans", "solution", "est", 1, "problème", "mal", "posé"]
print(c)
for i in range(len(c)):
print(type(c[i]))
Ce qui produit le résultat suivant :
6.1.4. Slicing
La simplicité est encore plus évidente quand on aborde le slicing (découpage) :
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
print(alpha[4:16])
Ce qui produit le résultat suivant :
EFGHIJKLMNOP
En C on utiliserait une fonction comme strncpy() ou memcpy(), plus complexes et dangereuses pour les débutants, et qui nécessitent une allocation mémoire.
En Python, les lignes suivantes :
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
print(alpha[20:100])
Produisent le résultat suivant :
UVWXYZ
En clair, on a demandé une tranche de la chaîne s, située entre le 20ème caractère et le 100ème, alors que la chaîne a une longueur de seulement 26 caractères. On l'aura compris, Python est un langage qui apporte de la sécurité.
Comment récupérer le dernier élément d'une séquence ? comme ceci :
a = "abcdef"
print(a[-1])
6.1.5. Introspection
On appelle introspection la capacité à examiner les classes, fonctions et mots-clés pour savoir ce qu'ils sont, ce qu'ils font et ce qu'ils connaissent.
Écrivons une classe et un peu de code :
name = ""
present = False
def __init__(self, name):
self.name = name
def enter(self):
self.present = True
def exit(self):
''' the student leaves school '''
self.present = False
john = student("john")
print("john:")
print(john)
print("id(john):")
print(id(john))
print('dir("john"):')
print(dir(john))
print('john.__class__:')
print(john.__class__)
print('dir(john.present):')
print(dir(john.present))
print('dir(john.enter):')
print(dir(john.enter))
Ce qui produit le résultat suivant :
Examinons de plus près :
print("john:")print(john)
print(john) dit que john est un objet de la classe student situé dans le module __main__, et que son identifiant est 0x7024a0d6ef00
print("id(john):")print(id(john))
id(john) nous donne l'identifiant de l'objet john : 126360425639824 (0x7024a0d6ef00 en décimal)
print(dir(john))
dir("john"):
dir(john) retourne les membres de l'objet john. Les méthodes que nous avons écrites sont présentes, parmi d'autres membres.
print(john.__class__)
john.__class__ contient le nom de la classe de l'objet john : __main__.student
print(dir(john.present))
dir(john.present) retourne les attributs de l'attribut present de l'objet john.
print('dir(john.enter):')
print(dir(john.enter))
dir(john.enter):
['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__func__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
print(dir(john.enter))
dir(john.enter):
['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__func__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
dir(john.enter) retourne les attributs de la méthode enter() de l'objet john.
dir(john.enter) retourne les attributs de la méthode enter() de l'objet john.
print('callable(getattr(john, "enter")):')print(callable(getattr(john, "enter")))
callable(getattr(john, "enter")):
True
callable(getattr(john, "enter")):
True
callable(getattr(john, "enter")) permet de savoir si le membre enter de l'objet john est appelable.
On peut remarquer sur cette ligne l'utilisation de simples et doubles quotes imbriquées :
print('callable(getattr(john, "enter")):')Ce qui permet de ne pas fermer la chaîne sur la première double quote de "enter".
On aurait pu écrire aussi :
print("callable(getattr(john, 'enter')):")Ou, comme en C :
print("callable(getattr(john, \"enter\")):")En Python on peut indifféremment utiliser la simple ou la double quote pour encadrer une chaîne, comme en JavaScript.
On constate qu'en Python tout est orienté objet, qu'il s'agisse de classe, d'instances, d'attributs et méthodes. Je vous laisse imaginer les possibilités offertes par toutes ces méthodes d'introspection.
callable(getattr(john, "enter")) permet de savoir si le membre enter de l'objet john est appelable.
On peut remarquer sur cette ligne l'utilisation de simples et doubles quotes imbriquées :
Ce qui permet de ne pas fermer la chaîne sur la première double quote de "enter".
On aurait pu écrire aussi :
Ou, comme en C :
En Python on peut indifféremment utiliser la simple ou la double quote pour encadrer une chaîne, comme en JavaScript.
On constate qu'en Python tout est orienté objet, qu'il s'agisse de classe, d'instances, d'attributs et méthodes. Je vous laisse imaginer les possibilités offertes par toutes ces méthodes d'introspection.
6.1.6. Et les pointeurs ?
En Python, la notion de pointeur n'existe tout simplement pas. C'est certainement une bonne nouvelle pour les débutants.
6.2. La ligne série
Quand on travaille avec un ARDUINO ou un ESP, il est assez courant d'avoir recours au moniteur série pour afficher des information sur l'écran du PC.
Mais c'est assez limité. Que faire si l'on a besoin d’interagir avec le logiciel embarqué ? La ligne série, accessible via le connecteur USB de la carte, semble le moyen le plus simple.
J'ai déjà traité ce sujet ici : Commander un ARDUINO par la ligne série ou BLUETOOTH
Pour communiquer en série à partir de Python, il vous faudra installer le package PySerial.
Certains d'entre vous ont peut être déjà développé des logiciel de communication série en C à l'aide de Win32 sous Windows, ou termios sous Linux. Sous Windows, on peut très vite constater que cela peut très vite provoquer des problèmes en fonction de la cible. On logiciel peut très bien fonctionner sur certains PC et mal fonctionner sur d'autres (c'est du vécu). Il faut vraiment être un spécialiste de Win32 pour s'en sortir. Sous Linux c'est beaucoup moins le cas.
Mais dans tous les cas, avec PySerial votre code fonctionnera aussi bien sur Windows que MacOs ou Linux. Seule l'ouverture de la ligne série diffère :
Sous Linux :
ser = serial.Serial('/dev/ttyUSB0')
Sous Windows :
ser = serial.Serial('COM1')
6.3. L'interface graphique
En matière d'interface graphique, on peut en Python se contenter de TkInter, qui produit des résultats honorables mais assez peu esthétiques :
Interface graphique Tkinter python
On peut également utiliser WxPython, PyGTK, ou PyQT, qui sont des interfaces Python à WxWindows, GTK et QT.
On peut citer également PyGame, une librairie de dessin toute simple, sans widgets.
Mais à l'heure actuelle ces librairies sont de moins en moins utilisées, la création d'interfaces graphiques se faisant principalement en HTML, JavaScript et CSS.
6.4. Le serveur WEB
Il existe une grande variété de serveurs WEB écrits en PYTHON :
- http.server
- CherryPy
- Django
- Flask
- etc
6.4.1. http.server
http.server fait partie de la librairie standard Python. Examinons cet exemple simple :
Si l'on lance ce serveur en local il affichera sur la console :
Dans le navigateur on entrera :
http://localhost:8080/index
ou :
http://localhost:8080/
Le navigateur affichera simplement : This is my web server
On peut ajouter une URL supplémentaire nommée alternative :
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
hostName = "127.0.0.1"
serverPort = 8080
class MyServer(BaseHTTPRequestHandler):
def do_GET(self):
if(self.path == '/' or self.path == '/index'):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes("<html><head><title>My Web Server</title></head>", "utf-8"))
self.wfile.write(bytes("<body>", "utf-8"))
self.wfile.write(bytes("<p>This is my web server</p>", "utf-8"))
self.wfile.write(bytes("</body></html>", "utf-8"))
elif(self.path == '/alternative'):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes("<html><head><title>My Web Server</title></head>", "utf-8"))
self.wfile.write(bytes("<body>", "utf-8"))
self.wfile.write(bytes("<p>This is another URL</p>", "utf-8"))
self.wfile.write(bytes("</body></html>", "utf-8"))
if __name__ == "__main__":
webServer = HTTPServer((hostName, serverPort), MyServer)
print("Server started at http://%s:%s" % (hostName, serverPort))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server stopped.")
Dans le navigateur on entrera :
http://localhost:8080/alternative
Le navigateur affichera alors : This is another URL
6.4.2. CherryPy
Cherrypy propose une approche intéressante :
Chaque méthode de la classe HelloWorld est exposée à l'aide du mot clé (appelé décorateur) @cherrypy.expose. Elle sera donc appelée lorsque l'URL nommée index sera entrée dans la barre d'adresse du navigateur, mais également l'URL nommée /.
Si l'on lance ce serveur en local il affichera sur la console :
[06/Dec/2025:15:54:57] ENGINE Listening for SIGTERM.
[06/Dec/2025:15:54:57] ENGINE Listening for SIGHUP.
[06/Dec/2025:15:54:57] ENGINE Listening for SIGUSR1.
[06/Dec/2025:15:54:57] ENGINE Bus STARTING
CherryPy Checker:
The Application mounted at '' has an empty config.
[06/Dec/2025:15:54:57] ENGINE Started monitor thread 'Autoreloader'.
[06/Dec/2025:15:54:57] ENGINE Serving on http://127.0.0.1:8080
[06/Dec/2025:15:54:57] ENGINE Bus STARTED
A noter que le port par défaut du serveur est le 8080.
Dans le navigateur on entrera :
http://localhost:8080/index
ou :
http://localhost:8080/
Le navigateur affichera simplement : Hello from CherryPy!
On peut ajouter une URL supplémentaire nommée alternative :
Dans le navigateur on entrera :
http://localhost:8080/alternative
Le navigateur affichera alors : Another Hello from CherryPy!
Simplissime ! Au final, pour ceux qui connaissent, comparer http.server à CherryPy revient à comparer les classes WebServer et AsyncWebServer quand on travaille sur ESP32. Quand on a goûté à CherryPy ou AsyncWebServer, il est difficile de revenir à http.server ou WebServer. On s'habitue vite au luxe.
Comme vous le savez peut être, AsyncWebServer est capable de gérer une page HTML en utilisant une template (un modèle). En Python la gestion des templates peut être confiée à Jinja2.
7. Générer un exécutable sous Windows
Quand on travaille avec Python, il est assez facile de distribuer ses logiciels à des utilisateurs Linux. En effet, Python est très souvent pré-installé sur la majeure partie des distributions.
Sous Windows, ce n'est pratiquement jamais le cas. Mais il existe un moyen : PyInstaller permet de générer un exécutable, un .exe !
Oui, vous avez bien lu. Vous pourrez ainsi distribuer votre logiciel de manière extrêmement simple, et de plus sans divulguer vos fichiers sources. La suite ici.
8. Conclusion
D'après de nombreux spécialistes Python est un langage de haut niveau, simple et facile à apprendre. De plus, de nombreuses librairies sont disponibles, ce qui simplifie encore plus le développement d'applications.
Malgré cela il a un inconvénient majeur : du fait que c'est un langage interprété, certaines erreurs de syntaxe sont détectées lors de l'exécution. Cela veut dire clairement que la phase de tests est un élément crucial dans le processus de développement. Mais cela ne veut pas dire que cela le rend moins fiable pour autant. En matière de développement, la phase de tests est en général aussi coûteuse que la phase de codage, quel que soit le langage. Il ne viendrait pas à l'idée d'un développeur professionnel de négliger ce fait.
Tout langage nécessite un apprentissage, qui requiert en général une semaine de labeur. Pour accéder à Python il n'en sera pas autrement, mais l'investissement sera très vite rentabilisé, bien au delà de ce que peut offrir C ou C++.
Cordialement
Henri


