Le threading réduit considérablement le temps d'exécution d'un programme. Apprenez à implémenter le threading en Python.

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'effectuer plusieurs tâches ou processus simultanément.

Vous apprendrez à utiliser le Python intégré enfilage modules et le fonctionnalités.simultanées module. Ces deux modules offrent des moyens simples de créer et de gérer des threads

Importance du filetage

Le threading réduit le temps nécessaire à un programme pour terminer 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.

Par exemple, un programme qui télécharge plusieurs fichiers image depuis Internet. Ce programme peut utiliser le threading pour télécharger les fichiers en parallèle plutôt qu'un à la fois. Cela élimine le temps que le programme aurait à attendre que le processus de téléchargement d'un fichier soit terminé avant de passer au suivant.

Programme initial avant l'enfilage

La fonction dans le programme suivant représente une tâche. La tâche consiste à suspendre 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 qu'il a fallu à l'ensemble du programme pour s'exécuter, puis l'affiche à l'écran.

importer temps

start_time = time.perf_counter()

définitivementpause():
imprimer('Dormir 1 seconde...')
le sommeil de temps(1)
imprimer('Fini de dormir...')

pause()
pause()
finish_time = time.perf_counter()
imprimer(f'Fini en {rond (heure_fin - heure_début, 2)} seconde(s)')

La sortie montre que le programme a pris 2,01 secondes pour s'exécuter. Chaque tâche prenait une seconde et le reste du code prenait 0,01 seconde à s'exécuter.

Vous pouvez utiliser le threading pour exécuter simultanément les deux tâches. Cela prendra une seconde aux deux tâches pour s'exécuter.

Implémentation du threading à l'aide du module threading

Pour modifier le code initial afin d'implémenter le threading, importez le enfilage module. Créer deux fils, fil_1 et fil_2 en utilisant le Fil classe. Appeler le commencer méthode sur chaque thread pour démarrer son exécution. Appeler le rejoindre sur chaque thread pour attendre que leur exécution se termine avant que le reste du programme ne s'exécute.

importer temps
importer enfilage
start_time = time.perf_counter()

définitivementpause():
imprimer('Dormir 1 seconde...')
le sommeil de temps(1)
imprimer('Fini de dormir...')

thread_1 = enfilage. Sujet (cible=pause)
thread_2 = enfilage. Sujet (cible=pause)

thread_1.start()
thread_2.start()

thread_1.join()
thread_2.join()

finish_time = time.perf_counter()
imprimer(f'Fini en {rond (heure_fin - heure_début, 2)} seconde(s)')

Le programme exécutera les deux threads simultanément. Cela réduira le temps nécessaire pour accomplir les 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 que le programme initial a pris.

Implémentation du threading à l'aide du module concurrent.futures

Python 3.2 a vu l'introduction de la contrats à terme concurrents 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 le ThreadPoolExecutor classe du module concurrent.futures pour créer un pool de threads. Soumettez le pause fonction à la piscine deux fois. Le soumettre méthode renvoie un avenir objet qui représente le résultat de l'appel de la fonction.

Itérer sur le contrats à terme et imprimer leurs résultats à l'aide de la résultat méthode.

importer temps
importer contrats à terme concurrents

start_time = time.perf_counter()

définitivementpause():
imprimer('Dormir 1 seconde...')
le sommeil de temps(1)
retour'Fini de dormir...'

avec contrats à terme.concurrents. ThreadPoolExecutor() comme exécuteur:
résultats = [executor.submit (pause) pour _ dans gamme(2)]
pour F dans concurrent.futures.as_completed (résultats) :
imprimer (f.result())

finish_time = time.perf_counter()

imprimer(f'Fini en {rond (heure_fin - heure_début, 2)} seconde(s)')

Le module concurrent.features s'occupe de démarrer et de rejoindre les threads pour vous. Cela rend votre code plus propre.

La sortie est identique à celle du module de filetage. Le module de threading est utile pour les cas simples où vous devez exécuter quelques threads en parallèle. D'autre part, le module concurrent.futures est utile pour les cas plus complexes où vous devez exécuter plusieurs 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 réduit le temps d'une seconde. Dans le monde réel, les threads font gagner plus de temps. Créez un programme qui télécharge des images depuis Internet. Commence par création d'un nouvel environnement virtuel. Exécutez la commande suivante dans le terminal pour installer le demandes bibliothèque:

demandes d'installation pip

La bibliothèque de requêtes vous permettra d'envoyer des requêtes HTTP. Importez la bibliothèque de requêtes et la bibliothèque de temps.

importer demandes
importer temps

Créez une liste d'URL des images que vous souhaitez télécharger. Laissez-les être au moins dix afin que vous puissiez remarquer une différence significative lorsque vous implémentez 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',
]

Boucle sur la liste d'URL téléchargeant chaque image dans le même dossier qui contient votre projet. Affichez le temps nécessaire pour télécharger les images en soustrayant l'heure de fin de l'heure de début.

start_time = time.perf_counter()
pour img_url dans img_url :
img_bytes = demandes.get (img_url).content
img_name = img_url.split('/')[3]
nom_img = F'{img_name}.jpg'
avec ouvrir (img_name, 'wb') comme fichier_img :
img_file.write (img_bytes)
imprimer(F'{img_name} a été téléchargé...')
finish_time = time.perf_counter()
imprimer(f'Fini en {finish_time - start_time} secondes')

Le programme prend environ 22 secondes pour télécharger les 12 images. Cela peut varier pour vous car le temps nécessaire pour télécharger les images dépend également de la vitesse de votre connexion 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 au exécuteur exemple.

importer demandes
importer temps
importer contrats à terme concurrents

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()

définitivementdownload_image(img_url):
img_bytes = demandes.get (img_url).content
img_name = img_url.split('/')[3]
nom_img = F'{img_name}.jpg'
avec ouvrir (img_name, 'wb') comme fichier_img :
img_file.write (img_bytes)
imprimer(F'{img_name} a été téléchargé...')

avec contrats à terme.concurrents. ThreadPoolExecutor() comme exécuteur:
executor.map (download_image, img_urls)

finish_time = time.perf_counter()

imprimer(f'Fini en {finish_time-start_time} secondes')

Après avoir introduit le filetage. Le temps diminue considérablement. Il n'a fallu que 4 secondes pour terminer l'exécution du programme.

Scénarios adaptés au threading

Certains des scénarios appropriés pour le threading sont :

  • Tâches liées aux E/S: Si le programme passe la majorité du temps à attendre la fin des opérations d'entrée ou de sortie. Le threading peut améliorer les performances en permettant à d'autres tâches de s'exécuter en attendant la fin des opérations d'E/S.
  • Récupération Web: Le scraping Web implique de faire des requêtes HTTP et d'analyser les réponses HTML. Le threading aide à accélérer le processus en vous permettant de faire plusieurs demandes simultanément.
  • Tâches liées au processeur: Le threading peut aider à améliorer les performances en permettant à plusieurs tâches de s'exécuter en parallèle.

Familiarisez-vous avec les threads dans d'autres langues

Python n'est pas le seul langage qui prend en charge le threading. La plupart des langages de programmation prennent en charge une certaine forme de threading. Il est important de se familiariser avec l'implémentation des threads dans d'autres langages. Cela vous donne les compétences nécessaires pour aborder différents scénarios où le threading peut s'appliquer.