Verfahren

Mehrere Threads in Python sind eigentlich keine echten Multi-Threads. Wenn Sie die Ressourcen einer Multi-Core-CPU voll ausnutzen möchten, müssen Sie in Python in den meisten Fällen mehrere Prozesse verwenden. Python bietet ein sehr benutzerfreundliches Multiprocessing-Paket. Sie müssen nur eine Funktion definieren und Python erledigt alles andere. Mit Hilfe dieses Pakets lässt sich die Umstellung von Einzelprozess auf gleichzeitige Ausführung problemlos bewerkstelligen. Multiprocessing unterstützt Unterprozesse, die Kommunikation und den Austausch von Daten, führt verschiedene Formen der Synchronisierung durch und stellt Komponenten wie Prozess, Warteschlange, Pipe und Sperre bereit.

1. Klassenprozess

Erstellen Sie eine Prozessklasse: Process([group [, target [, name [, args [, kwargs]]]]])

Ziel stellt das aufrufende Objekt dar

Argumente Ein Tupel von Positionsparametern, die das aufrufende Objekt darstellen

kwargs, die ein Wörterbuch des aufrufenden Objekts darstellen

Name ist ein Alias ​​

Gruppe wird im Wesentlichen nicht verwendet

Schauen wir uns die Erstellung der folgenden Funktion an und führen sie als mehrere Prozesse aus Beispiel:

#!/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!!!!!!!!!!!!!!!!!")

Ausgabeergebnisse:

Multiprozess-Ausgabeergebnisse

2. Erstellen Sie den Prozess als Klasse

Von Natürlich können wir einen Prozess auch als Klasse erstellen, wie im folgenden Beispiel, wenn der Prozess Wenn p start() aufruft, wird automatisch die run()-Methode aufgerufen.

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

Die Ausgabeergebnisse lauten wie folgt:

Prozessklasse erstellen

3. Daemon-Attribut

Möchten Sie wissen, was das ist? Daemon-Attribut wird verwendet? Schauen Sie sich die folgenden zwei Beispiele an. Attribut, eines wurde nicht hinzugefügt, vergleichen Sie das Ausgabeergebnis:

Beispiel für das Nichthinzufügen eines Deamon-Attributs:

# -*- 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】')

Ausgabeergebnis:

【EMD】
工作开始时间:Mon Oct  9 17:47:06 2017
工作结果时间:Mon Oct  9 17:47:09 2017

Im obigen Beispiel fügt Prozess p hinzu Daemon Attribut:

# -*- 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】')

Ausgabeergebnis:

【EMD】

Wenn das Daemon-Attribut dem untergeordneten Prozess hinzugefügt wird, endet laut Ausgabeergebnis auch der untergeordnete Prozess, wenn der Hauptprozess endet. Daher werden keine Informationen über den untergeordneten Prozess gedruckt.

4. Join-Methode

Um mit dem obigen Beispiel fortzufahren: Was sollten wir tun, wenn wir die Ausführung des untergeordneten Threads beenden möchten?

Dann können wir die Join-Methode verwenden. Die Hauptfunktion der Join-Methode besteht darin, den aktuellen Prozess zu blockieren, bis die Ausführung des Prozesses, der die Join-Methode aufruft, abgeschlossen ist, und dann mit der Ausführung des aktuellen Prozesses fortzufahren.

Sehen Sie sich also das Beispiel für das Hinzufügen der Join-Methode an:

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】')

Das Ausgabeergebnis:

工作开始时间:Tue Oct 10 11:30:08 2017
工作结果时间:Tue Oct 10 11:30:11 2017
【EMD】

5, Pool

Wenn viele untergeordnete Prozesse benötigt werden, müssen wir sie dann einzeln erstellen?

Natürlich nicht, wir können die Prozesspoolmethode verwenden, um untergeordnete Prozesse stapelweise zu erstellen.

Das Beispiel ist wie folgt:

# -*- 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】')

Das Ausgabeergebnis ist wie folgt:

主进程的 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】

Eines ist hier zu beachten: Das Pool-Objekt, das join() aufruft Die Methode wartet auf die Ausführung aller untergeordneten Prozesse. Abgeschlossen. Sie müssen close() aufrufen, bevor Sie join() aufrufen. Nach dem Aufruf von close() können Sie keine weiteren Prozesse hinzufügen.

Bitte achten Sie auf die Ausgabeergebnisse. Die untergeordneten Prozesse 0, 1, 2 und 3 werden sofort ausgeführt, während der untergeordnete Prozess 4 auf den Abschluss eines vorherigen untergeordneten Prozesses warten muss Die Standardgröße des Pools liegt bei uns. Auf meinem Computer beträgt sie 4, sodass höchstens 4 Prozesse gleichzeitig ausgeführt werden. Dies ist eine absichtliche Designbeschränkung von Pool, keine Einschränkung des Betriebssystems. Bei Änderung in:

p = Pool(5)

können 5 Prozesse gleichzeitig ausgeführt werden.

6. Kommunikation zwischen Prozessen

Das Betriebssystem stellt viele Mechanismen zur Verfügung, um eine Kommunikation zwischen Prozessen zu erreichen. Das Multiprocessing-Modul von Python umschließt den zugrunde liegenden Mechanismus und bietet mehrere Möglichkeiten zum Datenaustausch, z. B. Queue und Pipes.

Nehmen Sie die Warteschlange als Beispiel und erstellen Sie zwei untergeordnete Prozesse im übergeordneten Prozess. Einer schreibt Daten in die Warteschlange und der andere liest Daten aus der Warteschlange:

#!/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()

Das Ausgabeergebnis lautet:

读进程的PID:13208
写进程的PID:10864
写进 Queue 的值为:两点水
从 Queue 读取的值为:两点水
写进 Queue 的值为:三点水
从 Queue 读取的值为:三点水
写进 Queue 的值为:四点水
从 Queue 读取的值为:四点水
Weiter lernen
||
einreichenCode zurücksetzen