Heim  >  Artikel  >  Backend-Entwicklung  >  Beispielcode für Multiprozesse und Prozesspools (Verarbeitungsbibliothek) in Python

Beispielcode für Multiprozesse und Prozesspools (Verarbeitungsbibliothek) in Python

零下一度
零下一度Original
2017-06-16 11:13:102036Durchsuche

In diesem Artikel wird hauptsächlich die detaillierte Erläuterung des Multiprozess- und Prozesspools (Verarbeitungsbibliothek) von Python vorgestellt, der von großem praktischem Wert ist.

Umgebung: win7 +python2.7

Ich wollte schon immer Multiprozess oder Multithreading lernen, aber bevor ich mir nur ein paar Grundkenntnisse und eine einfache Einführung ansah, konnte ich nicht verstehen, wie man es anwendet , bis ich vor einiger Zeit ein Crawler-Projekt auf Github sah, das mehrere Prozesse und Multithreading-bezogene Inhalte umfasste, während ich Baidu-bezogene Wissenspunkte las, notiere jetzt einige relevante Wissenspunkte und einige Anwendungen für einen Datensatz

Lassen Sie uns zunächst darüber sprechen, was ein Prozess ist: Ein Prozess ist ein Programm auf dem Computer. Sobald eine Aktivität ausgeführt wird, wird ein Prozess gestartet Da der Prozess zum Ausführen verschiedener Funktionen des Betriebssystems verwendet wird, handelt es sich um einen Systemprozess, der sich im laufenden Zustand befindet. Das Betriebssystem selbst und alle von Ihnen gestarteten Prozesse sind Benutzerprozesse. Ein Prozess ist die Einheit, mit der das Betriebssystem Ressourcen zuweist.

Intuitiv ist der im Task-Manager mit System markierte Benutzername der Systemprozess und der mit Administrator markierte Benutzerprozess. Darüber hinaus ist „Netro“ und „Lcacal Service“ eine spezifischere Information Über den Prozess können Sie Enzyklopädie, hier müssen Sie sich etwas Mühe sparen, sonst können Sie ihn nicht zurücknehmen.

Einfache Verwendung von Multiprozess

Wie in der Abbildung gezeigt, hat Multiprocessing mehrere Funktionen, von denen ich viele noch nicht verstanden habe, daher werde ich nur über das sprechen, was ich bisher weiß

Prozesserstellung:Process(target=hauptsächlich Funktion ausführen, Name= Der benutzerdefinierte Prozessname muss nicht geschrieben werden, args=(Parameter))

Methode:

  1. is_alive(): Bestimmen Sie, ob der Prozess aktiv ist

  2. join([timeout]): Der untergeordnete Prozess endet, bevor der nächste Schritt ausgeführt wird. Manchmal ist die Zeitüberschreitung Der Prozess wird blockiert, damit das Programm weiterhin ausgeführt werden kann.

  3. run(): Wenn Sie beim Erstellen eines Prozessobjekts kein Ziel angeben, wird die Ausführungsmethode verwendet des Prozesses wird standardmäßig ausgeführt

  4. start(): Starten Sie den Prozess, unterscheiden Sie run()

  5. terminate(): Beenden Sie den Prozess . Den Prozess zu beenden ist nicht so einfach. Es scheint, dass es besser wäre, das psutil-Paket zu verwenden, wenn ich die Gelegenheit dazu habe.

Unter anderem startet Process einen Prozess mit start().

Attribute:

  1. authkey: Finden Sie diesen Satz in der Funktion authkey() im Dokument: Autorisierungsschlüssel des Prozesses festlegen. Autorisierungsschlüssel, es wurden bisher keine relevanten Anwendungsbeispiele gefunden. Wie wird dieser Schlüssel verwendet? Der

  2. Daemon wird automatisch beendet, nachdem der übergeordnete Prozess beendet wurde Es können keine neuen generiert werden. Der Prozess muss vor start() festgelegt werden >

  3. Name: Der Name des Prozesses, angepasst

  4. pid: Jeder Prozess hat eine eindeutige PID-Nummer.

  5. 1.Process(),start(),join()

Hier sind zwei Prozesse geöffnet, p1 und The 4 in p2 ist arg=(4,) der Parameter der Funktion fun1. Wenn es zwei oder mehr Parameter gibt, ist es arg=(Parameter 1, Parameter 2...) und dann Beginnen Sie mit start() Prozess, wir richten uns so ein, dass wir warten, bis die Prozesse p1 und p2 enden, bevor wir den nächsten Schritt ausführen. Wenn wir uns die folgenden Ausführungsergebnisse ansehen, beginnen fun2 und fun1 im Grunde gleichzeitig mit der Ausführung. fun1 schläft 4 Sekunden lang und fun2 schläft 6 Sekunden lang). in verschiedenen Positionen

Ergebnis:
# -*- coding:utf-8 -*-
from multiprocessing import Process
import time

def fun1(t):
 print 'this is fun1',time.ctime()
 time.sleep(t)
 print 'fun1 finish',time.ctime()

def fun2(t):
 print 'this is fun2',time.ctime()
 time.sleep(t)
 print 'fun2 finish',time.ctime()

if name == 'main':
 a=time.time()
 p1=Process(target=fun1,args=(4,))
 p2 = Process(target=fun2, args=(6,))
 p1.start()
 p2.start()
 p1.join()
 p2.join()
 b=time.time()
 print 'finish',b-a

Sehen Sie, jetzt führen wir zuerst die Funktion fun1 aus, dann führen wir die Funktion fun2 aus und geben dann „Finish“ aus, also „erste Ausführung“. Führen Sie den Prozess p1 aus und führen Sie dann den Prozess p2 aus. Probieren Sie nun die Kommentare aus. Entfernen Sie join() und sehen Sie, was erneut passiert. Ergebnis:
this is fun2 Mon Jun 05 13:48:04 2017
this is fun1 Mon Jun 05 13:48:04 2017
fun1 finish Mon Jun 05 13:48:08 2017
fun2 finish Mon Jun 05 13:48:10 2017
finish 6.20300006866

Process finished with exit code 0

Dieses Mal ist die Ausführung von fun1 beendet (da der Prozess p1 die Funktion join() verwendet, sodass das Hauptprogramm auf p1 wartet. Führen Sie nach dem Ausführen den nächsten Schritt aus), und fahren Sie dann mit der Ausführung des Drucks „Finish“ des Hauptprozesses fort Endlich beenden, nachdem fun2 die Ausführung beendet hat
# -*- coding:utf-8 -*-
from multiprocessing import Process
import time

def fun1(t):
 print 'this is fun1',time.ctime()
 time.sleep(t)
 print 'fun1 finish',time.ctime()

def fun2(t):
 print 'this is fun2',time.ctime()
 time.sleep(t)
 print 'fun2 finish',time.ctime()

if name == 'main':
 a=time.time()
 p1=Process(target=fun1,args=(4,))
 p2 = Process(target=fun2, args=(6,))
 p1.start()
 p1.join()
 p2.start()
 p2.join()
 b=time.time()
 print 'finish',b-a

this is fun1 Mon Jun 05 14:19:28 2017
fun1 finish Mon Jun 05 14:19:32 2017
this is fun2 Mon Jun 05 14:19:32 2017
fun2 finish Mon Jun 05 14:19:38 2017
finish 10.1229999065

Process finished with exit code 0
2.name,daemon,is_alive():

# -*- coding:utf-8 -*-
from multiprocessing import Process
import time

def fun1(t):
 print 'this is fun1',time.ctime()
 time.sleep(t)
 print 'fun1 finish',time.ctime()

def fun2(t):
 print 'this is fun2',time.ctime()
 time.sleep(t)
 print 'fun2 finish',time.ctime()

if name == 'main':
 a=time.time()
 p1=Process(target=fun1,args=(4,))
 p2 = Process(target=fun2, args=(6,))
 p1.start()
 p2.start()
 p1.join()
 #p2.join()
 b=time.time()
 print 'finish',b-a

Ergebnis:

this is fun1 Mon Jun 05 14:23:57 2017
this is fun2 Mon Jun 05 14:23:58 2017
fun1 finish Mon Jun 05 14:24:01 2017
finish 4.05900001526
fun2 finish Mon Jun 05 14:24:04 2017

Process finished with exit code 0

Wie Sie sehen können, besteht der Name darin, dem Prozess einen Namen zu geben und ihn auszuführen, um ihn auszudrucken. 'Prozess 1:',p1.is_alive(),'Prozess 2: ',p2.is_alive() Zum Zeitpunkt dieses Satzes , der p1-Prozess ist beendet (gibt False zurück) und der p2-Prozess läuft noch (gibt true zurück), aber p2 hat join() nicht verwendet, sodass der Hauptprozess aufgrund der Verwendung von Daemon = Ture direkt ausgeführt wurde wird automatisch beendet, nachdem der übergeordnete Prozess beendet wurde. Wenn der p2-Prozess nicht beendet wird, wird das gesamte Programm zwangsweise beendet

3.run()

run( ) ist im Prozess nicht vorhanden. Bei der Angabe der Zielfunktion wird standardmäßig die Funktion run() zum Ausführen des Programms verwendet.
# -*- coding:utf-8 -*-
from multiprocessing import Process
import time

def fun1(t):
 print 'this is fun1',time.ctime()
 time.sleep(t)
 print 'fun1 finish',time.ctime()

def fun2(t):
 print 'this is fun2',time.ctime()
 time.sleep(t)
 print 'fun2 finish',time.ctime()

if name == 'main':
 a=time.time()
 p1=Process(name='fun1进程',target=fun1,args=(4,))
 p2 = Process(name='fun2进程',target=fun2, args=(6,))
 p1.daemon=True
 p2.daemon = True
 p1.start()
 p2.start()
 p1.join()
 print p1,p2
 print '进程1:',p1.is_alive(),'进程2:',p2.is_alive()
 #p2.join()
 b=time.time()
 print 'finish',b-a

Ergebnis:
this is fun2 Mon Jun 05 14:43:49 2017
this is fun1 Mon Jun 05 14:43:49 2017
fun1 finish Mon Jun 05 14:43:53 2017
<Process(fun1进程, stopped daemon)> <Process(fun2进程, started daemon)>
进程1: False 进程2: True
finish 4.06500005722

Process finished with exit code 0

Aus dem Ergebnis: Es ist ersichtlich, dass Prozess p nichts bewirkt hat, damit der Prozess normal ausgeführt werden kann:

Die Zielfunktion hat keine Parameter:

Ergebnis:
# -*- coding:utf-8 -*-
from multiprocessing import Process
import time

def fun1(t):
 print &#39;this is fun1&#39;,time.ctime()
 time.sleep(t)
 print &#39;fun1 finish&#39;,time.ctime()

def fun2(t):
 print &#39;this is fun2&#39;,time.ctime()
 time.sleep(t)
 print &#39;fun2 finish&#39;,time.ctime()

if name == &#39;main&#39;:
 a = time.time()
 p=Process()
 p.start()
 p.join()
 b = time.time()
 print &#39;finish&#39;, b - a

Die Zielfunktion hat Parameter:
finish 0.0840001106262


Ergebnis:

Die Zielfunktion hat Parameter und eine Ausnahme ist aufgetreten. Ich habe den Grund noch nicht gefunden, aber in der Praxis habe ich festgestellt, dass diese Ausnahme auftritt, wenn der letzte Parameter dem Prozess übergeben und ausgeführt wird. Wenn jemand es weiß, lassen Sie es mich bitte wissen.
# -*- coding:utf-8 -*-
from multiprocessing import Process
import time

def fun1():
 print &#39;this is fun1&#39;,time.ctime()
 time.sleep(2)
 print &#39;fun1 finish&#39;,time.ctime()

def fun2(t):
 print &#39;this is fun2&#39;,time.ctime()
 time.sleep(t)
 print &#39;fun2 finish&#39;,time.ctime()

if name == &#39;main&#39;:
 a = time.time()
 p=Process()
 p.run=fun1
 p.start()
 p.join()
 b = time.time()
 print &#39;finish&#39;, b - a

2. Prozesspool
this is fun1 Mon Jun 05 16:34:41 2017
fun1 finish Mon Jun 05 16:34:43 2017
finish 2.11500000954

Process finished with exit code 0

对于需要使用几个甚至十几个进程时,我们使用Process还是比较方便的,但是如果要成百上千个进程,用Process显然太笨了,multiprocessing提供了Pool类,即现在要讲的进程池,能够将众多进程放在一起,设置一个运行进程上限,每次只运行设置的进程数,等有进程结束,再添加新的进程

Pool(processes =num):设置运行进程数,当一个进程运行完,会添加新的进程进去

apply_async(函数,(参数)):非阻塞,其中参数是tulpe类型,

apply(函数,(参数)):阻塞

close():关闭pool,不能再添加新的任务

terminate():结束运行的进程,不再处理未完成的任务

join():和Process介绍的作用一样, 但要在close或terminate之后使用。

1.单个进程池

# -*- coding:utf-8 -*-
from multiprocessing import Pool
import time

def fun1(t):
 print &#39;this is fun1&#39;,time.ctime()
 time.sleep(t)
 print &#39;fun1 finish&#39;,time.ctime()

def fun2(t):
 print &#39;this is fun2&#39;,time.ctime()
 time.sleep(t)
 print &#39;fun2 finish&#39;,time.ctime()

if name == &#39;main&#39;:
 a=time.time()
 pool = Pool(processes =3) # 可以同时跑3个进程
 for i in range(3,8):
  pool.apply_async(fun1,(i,))
 pool.close()
 pool.join()
 b=time.time()
 print &#39;finish&#39;,b-a

结果:

this is fun1 Mon Jun 05 15:15:38 2017
this is fun1 Mon Jun 05 15:15:38 2017
this is fun1 Mon Jun 05 15:15:38 2017
fun1 finish Mon Jun 05 15:15:41 2017
this is fun1 Mon Jun 05 15:15:41 2017
fun1 finish Mon Jun 05 15:15:42 2017
this is fun1 Mon Jun 05 15:15:42 2017
fun1 finish Mon Jun 05 15:15:43 2017
fun1 finish Mon Jun 05 15:15:47 2017
fun1 finish Mon Jun 05 15:15:49 2017
finish 11.1370000839

Process finished with exit code 0

从上面的结果可以看到,设置了3个运行进程上限,15:15:38这个时间同时开始三个进程,当第一个进程结束时(参数为3秒那个进程),会添加新的进程,如此循环,直至进程池运行完再执行主进程语句b=time.time() print 'finish',b-a .这里用到非阻塞apply_async(),再来对比下阻塞apply()

# -*- coding:utf-8 -*-
from multiprocessing import Pool
import time

def fun1(t):
 print &#39;this is fun1&#39;,time.ctime()
 time.sleep(t)
 print &#39;fun1 finish&#39;,time.ctime()

def fun2(t):
 print &#39;this is fun2&#39;,time.ctime()
 time.sleep(t)
 print &#39;fun2 finish&#39;,time.ctime()

if name == &#39;main&#39;:
 a=time.time()
 pool = Pool(processes =3) # 可以同时跑3个进程
 for i in range(3,8):
  pool.apply(fun1,(i,))
 pool.close()
 pool.join()
 b=time.time()
 print &#39;finish&#39;,b-a

结果:

this is fun1 Mon Jun 05 15:59:26 2017
fun1 finish Mon Jun 05 15:59:29 2017
this is fun1 Mon Jun 05 15:59:29 2017
fun1 finish Mon Jun 05 15:59:33 2017
this is fun1 Mon Jun 05 15:59:33 2017
fun1 finish Mon Jun 05 15:59:38 2017
this is fun1 Mon Jun 05 15:59:38 2017
fun1 finish Mon Jun 05 15:59:44 2017
this is fun1 Mon Jun 05 15:59:44 2017
fun1 finish Mon Jun 05 15:59:51 2017
finish 25.1610000134

Process finished with exit code 0

可以看到,阻塞是当一个进程结束后,再进行下一个进程,一般我们都用非阻塞apply_async()

2.多个进程池

上面是使用单个进程池的,对于多个进程池,我们可以用for循环,直接看代码

# -*- coding:utf-8 -*-
from multiprocessing import Pool
import time

def fun1(t):
 print &#39;this is fun1&#39;,time.ctime()
 time.sleep(t)
 print &#39;fun1 finish&#39;,time.ctime()

def fun2(t):
 print &#39;this is fun2&#39;,time.ctime()
 time.sleep(t)
 print &#39;fun2 finish&#39;,time.ctime()

if name == &#39;main&#39;:
 a=time.time()
 pool = Pool(processes =3) # 可以同时跑3个进程
 for fun in [fun1,fun2]:
  for i in range(3,8):
   pool.apply_async(fun,(i,))
 pool.close()
 pool.join()
 b=time.time()
 print &#39;finish&#39;,b-a

结果:

this is fun1 Mon Jun 05 16:04:38 2017
this is fun1 Mon Jun 05 16:04:38 2017
this is fun1 Mon Jun 05 16:04:38 2017
fun1 finish Mon Jun 05 16:04:41 2017
this is fun1 Mon Jun 05 16:04:41 2017
fun1 finish Mon Jun 05 16:04:42 2017
this is fun1 Mon Jun 05 16:04:42 2017
fun1 finish Mon Jun 05 16:04:43 2017
this is fun2 Mon Jun 05 16:04:43 2017
fun2 finish Mon Jun 05 16:04:46 2017
this is fun2 Mon Jun 05 16:04:46 2017
fun1 finish Mon Jun 05 16:04:47 2017
this is fun2 Mon Jun 05 16:04:47 2017
fun1 finish Mon Jun 05 16:04:49 2017
this is fun2 Mon Jun 05 16:04:49 2017
fun2 finish Mon Jun 05 16:04:50 2017
this is fun2 Mon Jun 05 16:04:50 2017
fun2 finish Mon Jun 05 16:04:52 2017
fun2 finish Mon Jun 05 16:04:55 2017
fun2 finish Mon Jun 05 16:04:57 2017
finish 19.1670000553

Process finished with exit code 0

看到了,在fun1运行完接着运行fun2.

另外对于没有参数的情况,就直接 pool.apply_async(funtion),无需写上参数.

在学习编写程序过程,曾遇到不用if _name_ == '_main_':而直接运行程序,这样结果会出错,经查询,在Windows上要想使用进程模块,就必须把有关进程的代码写在当前.py文件的if _name_ == ‘_main_' :语句的下面,才能正常使用Windows下的进程模块。Unix/Linux下则不需要。原因有人这么说:在执行的時候,由于你写的 py 会被当成module 读进执行。所以,一定要判断自身是否为 _main_。也就是要:

if name == ‘main&#39; :
# do something.

这里我自己还搞不清楚,期待以后能够理解

Das obige ist der detaillierte Inhalt vonBeispielcode für Multiprozesse und Prozesspools (Verarbeitungsbibliothek) in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn