Le temps d’exécution est l’une des mesures courantes de l’efficacité d’un programme. Plus le temps d’exécution est rapide, meilleur est le programme. Le threading est une technique qui permet à un programme d’exécuter plusieurs tâches ou processus simultanément.
Vous apprendrez à utiliser les fonctions intégrées de Python. threading et le module concurrent.features . Ces deux modules offrent des moyens simples de créer et de gérer des threads
Importance du threading
Le threading permet de réduire le temps nécessaire à un programme pour effectuer une tâche. Si le travail contient plusieurs tâches indépendantes, vous pouvez utiliser le threading pour exécuter les tâches simultanément, réduisant ainsi le temps d’attente du programme pour qu’une tâche se termine avant de passer à la suivante.
Prenons l’exemple d’un programme qui télécharge plusieurs fichiers d’images sur Internet. Ce programme peut utiliser le threading pour télécharger les fichiers en parallèle plutôt qu’un par un. Ainsi, le programme n’a pas à attendre la fin du téléchargement d’un fichier avant de passer au suivant.
Programme initial avant le threading
La fonction du programme suivant représente une tâche. La tâche consiste à interrompre l’exécution du programme pendant une seconde. Le programme appelle la fonction deux fois, créant ainsi deux tâches. Il calcule ensuite le temps d’exécution de l’ensemble du programme et l’affiche à l’écran.
import time
start_time = time.perf_counter()
def pause():
print('Sleeping 1 second...')
time.sleep(1)
print('Done Sleeping...')
pause()
pause()
finish_time = time.perf_counter()
print(f'Finished in {round(finish_time - start_time, 2)} second(s)')
La sortie montre que le programme a mis 2,01 secondes à s’exécuter. Chaque tâche a pris une seconde et le reste du code a pris 0,01 seconde pour s’exécuter.
Vous pouvez utiliser le threading pour exécuter les deux tâches simultanément. L’exécution des deux tâches prendra une seconde.
Mise en œuvre du threading Utilisation du module threading
Pour modifier le code initial afin d’implémenter le threading, importez le module threading module. Créer deux threads, thread_1 et fil_2 Utilisation de l’outil Fil classe. Appeler la classe début sur chaque thread pour démarrer son exécution. L’appel de la méthode joindre sur chaque thread pour attendre la fin de leur exécution avant que le reste du programme ne s’exécute.
import time
import threading
start_time = time.perf_counter()
def pause():
print('Sleeping 1 second...')
time.sleep(1)
print('Done Sleeping...')
thread_1 = threading.Thread(target=pause)
thread_2 = threading.Thread(target=pause)
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
finish_time = time.perf_counter()
print(f'Finished in {round(finish_time - start_time, 2)} second(s)')
Le programme exécutera les deux threads simultanément. Cela réduira le temps nécessaire à l’accomplissement des deux tâches.
La sortie montre que le temps nécessaire pour exécuter les mêmes tâches est d’environ une seconde. C’est la moitié du temps pris par le programme initial.
Implémentation du Threading à l’aide du module concurrent.futures
Python 3.2 a vu l’introduction du module concurrent.futures module. Ce module fournit une interface de haut niveau pour l’exécution de tâches asynchrones à l’aide de threads. Il fournit un moyen plus simple d’exécuter des tâches en parallèle.
Pour modifier le programme initial afin d’utiliser le threading, importez le module concurrent.features. Utilisez la fonction ThreadPoolExecutor du module concurrent.futures pour créer un pool de threads. Soumettre la classe pause La fonction d’assistance à la piscine a été remplie deux fois. La fonction soumettre renvoie un futur qui représente le résultat de l’appel de la fonction.
Itérer sur l’objet futurs et d’imprimer leurs résultats à l’aide de la fonction résultat méthode.
import time
import concurrent.futures
start_time = time.perf_counter()
def pause():
print('Sleeping 1 second...')
time.sleep(1)
return 'Done Sleeping...'
with concurrent.futures.ThreadPoolExecutor() as executor:
results = [executor.submit(pause) for _ in range(2)]
for f in concurrent.futures.as_completed(results):
print(f.result())
finish_time = time.perf_counter()
print(f'Finished in {round(finish_time - start_time, 2)} second(s)')
Le module concurrent.features se charge de démarrer et de rejoindre les threads pour vous. Cela rend votre code plus propre.
La sortie est identique à celle du module de threading. Le module threading est utile pour les cas simples où vous devez exécuter quelques threads en parallèle. En revanche, le module concurrent.futures est utile pour les cas plus complexes où vous devez exécuter de nombreuses tâches simultanément.
Utiliser le threading dans un scénario réel
L’utilisation de threads pour exécuter le programme ci-dessus a permis de réduire le temps d’une seconde. Dans le monde réel, les threads permettent de gagner encore plus de temps. Créez un programme qui télécharge des images à partir d’Internet. Commencez par créer un nouvel environnement virtuel. Exécutez la commande suivante dans le terminal pour installer le programme requêtes bibliothèque :
pip install requests
La bibliothèque requests vous permettra d’envoyer des requêtes HTTP. Importez la bibliothèque requests et la bibliothèque time.
import requests
import time
Créez une liste d’URL des images que vous souhaitez télécharger. Laissez-les au moins dix pour que vous puissiez remarquer une différence significative lorsque vous mettrez en œuvre le threading.
img_urls = [
'https://images.unsplash.com/photo-1524429656589-6633a470097c',
'https://images.unsplash.com/photo-1530224264768-7ff8c1789d79',
'https://images.unsplash.com/photo-1564135624576-c5c88640f235',
'https://images.unsplash.com/photo-1541698444083-023c97d3f4b6',
'https://images.unsplash.com/photo-1522364723953-452d3431c267',
'https://images.unsplash.com/photo-1513938709626-033611b8cc03',
'https://images.unsplash.com/photo-1507143550189-fed454f93097',
'https://images.unsplash.com/photo-1493976040374-85c8e12f0c0e',
'https://images.unsplash.com/photo-1504198453319-5ce911bafcde',
'https://images.unsplash.com/photo-1530122037265-a5f1f91d3b99',
'https://images.unsplash.com/photo-1516972810927-80185027ca84',
'https://images.unsplash.com/photo-1550439062-609e1531270e',
]
Bouclez la liste des URL en téléchargeant chaque image dans le même dossier que celui qui contient votre projet. Affichez le temps de téléchargement des images en soustrayant le temps d’arrivée du temps de départ.
start_time = time.perf_counter()
for img_url in img_urls:
img_bytes = requests.get(img_url).content
img_name = img_url.split("https://www.makeuseof.com/")[3]
img_name = f'{img_name}.jpg'
with open(img_name, 'wb') as img_file:
img_file.write(img_bytes)
print(f'{img_name} was downloaded...')
finish_time = time.perf_counter()
print(f'Finished in {finish_time - start_time} seconds')
Le programme prend environ 22 secondes pour télécharger les 12 images. Cette durée peut varier en fonction de votre vitesse d’accès à Internet.
Modifiez le programme pour utiliser le threading à l’aide du module concurrent.features. Au lieu d’une boucle, utilisez une fonction. C’est la fonction que vous passerez à la fonction exécuteur instance.
import requests
import time
import concurrent.futures
img_urls = [
'https://images.unsplash.com/photo-1524429656589-6633a470097c',
'https://images.unsplash.com/photo-1530224264768-7ff8c1789d79',
'https://images.unsplash.com/photo-1564135624576-c5c88640f235',
'https://images.unsplash.com/photo-1541698444083-023c97d3f4b6',
'https://images.unsplash.com/photo-1522364723953-452d3431c267',
'https://images.unsplash.com/photo-1513938709626-033611b8cc03',
'https://images.unsplash.com/photo-1507143550189-fed454f93097',
'https://images.unsplash.com/photo-1493976040374-85c8e12f0c0e',
'https://images.unsplash.com/photo-1504198453319-5ce911bafcde',
'https://images.unsplash.com/photo-1530122037265-a5f1f91d3b99',
'https://images.unsplash.com/photo-1516972810927-80185027ca84',
'https://images.unsplash.com/photo-1550439062-609e1531270e',
]
start_time = time.perf_counter()
def download_image(img_url):
img_bytes = requests.get(img_url).content
img_name = img_url.split("https://www.makeuseof.com/")[3]
img_name = f'{img_name}.jpg'
with open(img_name, 'wb') as img_file:
img_file.write(img_bytes)
print(f'{img_name} was downloaded...')
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.map(download_image, img_urls)
finish_time = time.perf_counter()
print(f'Finished in {finish_time-start_time} seconds')
Après l’introduction du threading. Le temps se réduit considérablement. L’exécution du programme n’a pris que 4 secondes.
Scénarios adaptés au threading
Voici quelques-uns des scénarios qui se prêtent à l’utilisation du threading :
- Tâches liées aux E/S: Si le programme passe la majeure partie du temps à attendre que les opérations d’entrée ou de sortie se terminent. Le threading peut améliorer les performances en permettant à d’autres tâches de s’exécuter en attendant que les opérations d’entrée/sortie se terminent.
- Web scraping: Le scraping web consiste à effectuer des requêtes HTTP et à analyser les réponses HTML. Le threading permet d’accélérer le processus en vous permettant d’effectuer plusieurs requêtes simultanément.
- Tâches liées à l’unité centrale: Le threading peut contribuer à améliorer les performances en permettant à plusieurs tâches de s’exécuter en parallèle.
Se familiariser avec le Threading dans d’autres langages
Python n’est pas le seul langage à prendre en charge le threading. La plupart des langages de programmation prennent en charge une forme ou une autre de threading. Il est important de se familiariser avec l’implémentation des threads dans d’autres langages. Cela vous permettra d’acquérir les compétences nécessaires pour aborder les différents scénarios dans lesquels le threading peut s’appliquer.