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 读取的值为:四点水
Formation continue
  • Recommandations de cours
  • Téléchargement du didacticiel