processus
Les threads multiples en Python ne sont en fait pas de véritables multi-threads. Si vous souhaitez utiliser pleinement les ressources d'un processeur multicœur, vous devez dans la plupart des cas utiliser plusieurs processus en Python. Python fournit un package multitraitement très simple à utiliser. Il vous suffit de définir une fonction et Python fera tout le reste. Avec l'aide de ce package, la conversion d'un processus unique à une exécution simultanée peut être facilement réalisée. Le multitraitement prend en charge les sous-processus, la communication et le partage de données, effectue différentes formes de synchronisation et fournit des composants tels que Processus, Queue, Pipe et Lock.
1. Class Process
La classe qui crée le processus : Process([group [, target [, name [, args [, kwargs]]]]])
target représente l'objet appelant
args représente l'objet appelant Le tuple de paramètres de position
kwargs représente le dictionnaire de l'objet appelant
le nom est un alias
le groupe n'est essentiellement pas utilisé
Regardons un exemple de création d'une fonction et de son utilisation comme plusieurs processus :
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- import multiprocessing import time def worker(interval, name): print(name + '【start】') time.sleep(interval) print(name + '【end】') if __name__ == "__main__": p1 = multiprocessing.Process(target=worker, args=(2, '两点水1')) p2 = multiprocessing.Process(target=worker, args=(3, '两点水2')) p3 = multiprocessing.Process(target=worker, args=(4, '两点水3')) p1.start() p2.start() p3.start() print("The number of CPU is:" + str(multiprocessing.cpu_count())) for p in multiprocessing.active_children(): print("child p.name:" + p.name + "\tp.id" + str(p.pid)) print("END!!!!!!!!!!!!!!!!!")
Résultats de sortie :
Résultats de sortie multi-processus
2. Créer un processus dans une classe
Bien sûr, nous pouvons également créer un processus dans une classe, comme dans l'exemple ci-dessous, lorsque le processus p appelle start() , la méthode run() est automatiquement appelée.
# -*- coding: UTF-8 -*- import multiprocessing import time class ClockProcess(multiprocessing.Process): def __init__(self, interval): multiprocessing.Process.__init__(self) self.interval = interval def run(self): n = 5 while n > 0: print("当前时间: {0}".format(time.ctime())) time.sleep(self.interval) n -= 1 if __name__ == '__main__': p = ClockProcess(3) p.start()
Les résultats de sortie sont les suivants :
Créer une classe de processus
3 Attribut de démon
Si vous voulez savoir à quoi sert l'attribut de démon, jetez un œil aux deux exemples suivants, l'un avec le attribut de démon ajouté et un sans, comparez le résultat de sortie :
Exemple sans ajouter d'attribut de démon :
# -*- coding: UTF-8 -*- import multiprocessing import time def worker(interval): print('工作开始时间:{0}'.format(time.ctime())) time.sleep(interval) print('工作结果时间:{0}'.format(time.ctime())) if __name__ == '__main__': p = multiprocessing.Process(target=worker, args=(3,)) p.start() print('【EMD】')
Résultat de sortie :
【EMD】 工作开始时间:Mon Oct 9 17:47:06 2017 工作结果时间:Mon Oct 9 17:47:09 2017
Dans l'exemple ci-dessus, le processus p ajoute l'attribut de démon :
# -*- coding: UTF-8 -*- import multiprocessing import time def worker(interval): print('工作开始时间:{0}'.format(time.ctime())) time.sleep(interval) print('工作结果时间:{0}'.format(time.ctime())) if __name__ == '__main__': p = multiprocessing.Process(target=worker, args=(3,)) p.daemon = True p.start() print('【EMD】')
Résultat de sortie :
【EMD】
Il Peut être vu en fonction du résultat de sortie, si dans le processus enfant L'attribut démon est ajouté à , donc lorsque le processus principal se termine, le processus enfant se terminera également. Aucune information sur le processus enfant n'est donc imprimée.
4. Méthode Join
En continuant avec l'exemple ci-dessus, que devons-nous faire si nous voulons que le thread enfant termine son exécution ?
Ensuite, nous pouvons utiliser la méthode join.La fonction principale de la méthode join est de bloquer le processus en cours jusqu'à ce que le processus qui appelle la méthode join termine son exécution, puis de continuer à exécuter le processus en cours.
Regardez donc l'exemple d'ajout de la méthode join :
import multiprocessing import time def worker(interval): print('工作开始时间:{0}'.format(time.ctime())) time.sleep(interval) print('工作结果时间:{0}'.format(time.ctime())) if __name__ == '__main__': p = multiprocessing.Process(target=worker, args=(3,)) p.daemon = True p.start() p.join() print('【EMD】')
Le résultat de sortie :
工作开始时间:Tue Oct 10 11:30:08 2017 工作结果时间:Tue Oct 10 11:30:11 2017 【EMD】
5, Pool
Si de nombreux processus enfants sont nécessaires, devons-nous les créer un par un ?
Bien sûr que non, nous pouvons utiliser la méthode du pool de processus pour créer des processus enfants par lots.
L'exemple est le suivant :
# -*- coding: UTF-8 -*- from multiprocessing import Pool import os, time, random def long_time_task(name): print('进程的名称:{0} ;进程的PID: {1} '.format(name, os.getpid())) start = time.time() time.sleep(random.random() * 3) end = time.time() print('进程 {0} 运行了 {1} 秒'.format(name, (end - start))) if __name__ == '__main__': print('主进程的 PID:{0}'.format(os.getpid())) p = Pool(4) for i in range(6): p.apply_async(long_time_task, args=(i,)) p.close() # 等待所有子进程结束后在关闭主进程 p.join() print('【End】')
Le résultat de sortie est le suivant :
主进程的 PID:7256 进程的名称:0 ;进程的PID: 1492 进程的名称:1 ;进程的PID: 12232 进程的名称:2 ;进程的PID: 4332 进程的名称:3 ;进程的PID: 11604 进程 2 运行了 0.6500370502471924 秒 进程的名称:4 ;进程的PID: 4332 进程 1 运行了 1.0830621719360352 秒 进程的名称:5 ;进程的PID: 12232 进程 5 运行了 0.029001712799072266 秒 进程 4 运行了 0.9720554351806641 秒 进程 0 运行了 2.3181326389312744 秒 进程 3 运行了 2.5331451892852783 秒 【End】
Il y a une chose à noter ici : l'appel de la méthode join() de l'objet Pool attendra que tous les processus enfants terminent leur exécution, et close() doit être appelé avant d'appeler join(). Après avoir appelé close(), vous ne pouvez pas continuer à ajouter de nouveaux processus.
Veuillez faire attention aux résultats de sortie. Les processus enfants 0, 1, 2 et 3 sont exécutés immédiatement, tandis que le processus enfant 4 doit attendre la fin d'un processus enfant précédent avant de s'exécuter. sur mon ordinateur est 4, donc un maximum de 4 processus peuvent être exécutés simultanément. Il s'agit d'une limitation intentionnelle de la conception de Pool, et non d'une limitation du système d'exploitation. Si vous le remplacez par :
p = Pool(5)
, vous pouvez exécuter 5 processus en même temps.
6. Communication inter-processus
Les processus doivent absolument communiquer. Le système d'exploitation fournit de nombreux mécanismes pour réaliser la communication inter-processus. Le module multitraitement de Python englobe le mécanisme sous-jacent et fournit plusieurs façons d'échanger des données, telles que la file d'attente et les tuyaux.
Prenons l'exemple de la file d'attente, créez deux processus enfants dans le processus parent, l'un écrit les données dans la file d'attente et l'autre lit les données de la file d'attente :
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- from multiprocessing import Process, Queue import os, time, random def write(q): # 写数据进程 print('写进程的PID:{0}'.format(os.getpid())) for value in ['两点水', '三点水', '四点水']: print('写进 Queue 的值为:{0}'.format(value)) q.put(value) time.sleep(random.random()) def read(q): # 读取数据进程 print('读进程的PID:{0}'.format(os.getpid())) while True: value = q.get(True) print('从 Queue 读取的值为:{0}'.format(value)) if __name__ == '__main__': # 父进程创建 Queue,并传给各个子进程 q = Queue() pw = Process(target=write, args=(q,)) pr = Process(target=read, args=(q,)) # 启动子进程 pw pw.start() # 启动子进程pr pr.start() # 等待pw结束: pw.join() # pr 进程里是死循环,无法等待其结束,只能强行终止 pr.terminate()
Le résultat de sortie est :
读进程的PID:13208 写进程的PID:10864 写进 Queue 的值为:两点水 从 Queue 读取的值为:两点水 写进 Queue 的值为:三点水 从 Queue 读取的值为:三点水 写进 Queue 的值为:四点水 从 Queue 读取的值为:四点水