Python

Dernière mise à jour : 22/10/2021

Les bases

Multithreading

A ne pas confondre avec multiprocessing. Avec des threads, on lance des programmes en //, et le système d’exploitation ou le processus parent gère comme il veut. Le multiprocessing consiste à forcer l’utilisation des différents cœurs d’un processeur.

import random 
import sys from threading
import Thread
import time

class Attente(Thread):
"""Thread chargé simplement d'afficher une lettre dans la console."""
def __init__(self, tps):
Thread.__init__(self)
self.attente = tps
def run(self):
"""Code à exécuter pendant l'exécution du thread."""
time.sleep(self.attente)
sys.stdout.write("Fin thread d'attente de {}\n".format(self.attente))
sys.stdout.flush()

# Création des threads
thread_1 = Attente(4)
thread_2 = Attente(7)
thread_3 = Attente(9)

# Lancement des threads
thread_1.start()
thread_2.start()
thread_3.start()

# Attend que les threads se terminent
thread_1.join()
thread_2.join()
thread_3.join()
  • https://www.tutorialspoint.com/python3/python_multithreading.htm  

Les décorateurs

Les décorateurs font de la « métaprogrammation », à savoir qu’ils ajoutent du code autour d’une fonction. Par l’exemple :

# Exemple avec décorateur
@decorateur
def fonction(…):
    …

Son équivalent est :

# Exemple équivalent, sans décorateur
def fonction(…):
    …
fonction = decorateur(fonction)

Ça n’a l’air de rien, mais ça permet de faire plein de choses très évoluées.

Interface graphique (Qt)

Un des avantages de Python est d’être multi plate-forme (pas comme Java). Un des gros manque de Python est qu’il n’a pas d’interface graphique native, ou que ce qui est proposé en standard (Tkinter) n’est pas très développé. Certes cela permet de rester multi plate-formes, mais au prix d’un interface graphique assez peu évoluée.

Après quelques recherches, j’ai trouvé un outil lui aussi multi plate-formes permettant de réaliser de zolies interfaces graphiques avec Python : Qt.

Qt n’est pas toujours simple, ni gratuit, mais peut toutefois être utilisé avec certaines licences libres comme GPL v2 ou GPL v3, ce qui est chouette pour un développeur du dimanche comme moi.

Concepts essentiels

Tout d’abord, pour développer en Python + Qt, il faut installer la version open source de Qt, en faisant bien attention aux compatibilités de versions. Il faut également faire la liaison entre Python et Qt grâce au module PyQt ou à PySide2 (cette dernière étant maintenue par Qt).

Layout, Widget et événements

En Python 3 et Qt 5, la plupart des objets dont on a besoin seront dans PySide2.QtWidgets. Leur nom est assez explicite, genre QApplication, QMainWindow, QDialog, QGridLayout, QLabel, QLineEdit, QPushButton, QTable, QGroupBox, QDateEdit, etc.

La notion de layout est celle communément connue par les développeurs, et celles des événements également. Seule subtilité : les événements sont des signaux (SIGNAL) et les récepteurs ou gestionnaires d’événements sont de type SLOT. Chacun a son vocabulaire, mais comme les fonctions de Qt sont nommées d’après cela, autant le savoir.

Utilisation de l’outil de conception

Il s’appelle QT Designer, mais sous Windows il faut chercher… designer !

Ensuite, le fichier issu de cet outil est en XML, suffixé par .ui. Pour le convertir en Python, il faut utiliser un transformateur, variant selon le module python utilisé :

  • PyQt ==> pyuic5.exe fichier.ui -o fichier.py
  • PySide2 ==> pyside2-uic mainwindow.ui > ui_mainwindow.py

En ce qui concerne les ressources, genre icônes, la manipulation est plus complexe. D’abord il faut un fichier .qrc dans lequel on ajoute les emplacements des ressources, puis on génère avec un autre outil un fichier Python.

  • PyQt ==> pyrcc5.exe dossier/ressources.qrc -o ressources_rc.py -py3
  • PySide2 ==> pyside2-rcc ?

Pour développer

Compiler un script Python en .exe

Je ne sais pas si mon titre est très académique, mais l’idée est d’avoir un .exe de son zoli programme Python. J’ai trouvé plein de tutos sur le sujet et plusieurs outils.

Packaging, continuous integration

Je viens seulement de comprendre l’importance et l’utilité des environnements virtuels au sens Python : ça permet d’éviter de se marcher sur les pieds (avec des versions incompatibles de packages) mais aussi et surtout de repérer facilement les dépendances d’un programme (ou d’un projet).

Avant tout, il faut installer virtualenv via pip. Ensuite on crée un environnement virtuel puis on l’active avec les commandes suivantes :

virtualenv nom_environnement
nom_environnement\Scripts\activate.bat

Sur Windows, cela peut ressembler plutôt à cela :

python3 -m venv nom_environnement 
nom_environnement\Scripts\activate.bat 

Sous Linux, j’ai aussi trouvé :

python3 -m venv nom_environnement
source nom_environnement/bin/activate  

On se retrouve alors dans un pseudo-environnement virtuel, sans aucune dépendance ni package installé.

Astuce utile : pour lancer IDLE avec le contexte d’exécution de cet environnement virtuel, on peut le faire en ligne de commande en se plaçant dans le répertoire voulu et en lançant :

(venv) $ python -m idlelib.idle

Dépendances

Pour vérifier les packages qui ne sont plus à jour, la commande est :

pip list --outdated

Pour la mise-à-jour, il faut lancer :

pip install --upgrade package

Visual Studio Code

Ca a beau n’être qu’un éditeur de code (au départ), Visual Studio Code est un excellent outil qui sait s’adapter à tous les langages, Python y compris, et il sait même gérer les environnements virtuel et WSL (le Linux de Windows). Il suffit d’ajouter les extensions qui vont bien.

Un peu de sécurité

Un peu de réseau (sockets)

Il est très facile de manipuler des flux réseaux en Python.

Sockets

Ce sont des canaux de communications sur le réseau, qu’on définit par :

  • L’adresse IP (adresse sur serveur ou de la machine à contacter) ;
  • Le port (souvent 80 pour http) ;
  • Le type :
    • TCP (socket.SOCK_STREAM, orienté connexion) ou UDP (socket.SOCK_DGRAM, sans notion de connexion)
  • La famille :

Quelques trucs

Pour lister toutes les méthodes d’un objet :

>>> from optparse import OptionParser
>>> import inspect
>>> inspect.getmembers(type(objet), predicate=inspect.isfunction)

De façon plus brutale, on peut aussi faire plus simplement :

>>> import sys
>>> dir(sys)

Sources d’information

…et de formation.