Heim > Artikel > Backend-Entwicklung > Mehrprozessprogrammierung in Python verstehen
Der folgende Editor vermittelt Ihnen ein tiefgreifendes Verständnis der Python-Multiprozessprogrammierung. Der Herausgeber findet es ziemlich gut, deshalb werde ich es jetzt mit Ihnen teilen und es allen als Referenz geben. Folgen wir dem Editor, um einen Blick darauf zu werfen
1. Hintergrund der Python-Multiprozessprogrammierung
Der größte Vorteil von Multiprozessen in Python ist Um die Ressourcen der Multi-Core-CPU voll auszunutzen, unterliegen sie nicht dem Multi-Threading in Python, das den GIL-Einschränkungen unterliegt, und können daher nur der CPU zugewiesen werden Grundsätzlich kann Multithreading verwendet werden, also grundsätzlich Sie können mehrere Prozesse verwenden.
Bei der Multiprozessprogrammierung ähnelt es tatsächlich dem Multithreading. Im Multithreading-Paket Threading gibt es eine Thread-Klasse Thread, in der es drei Methoden zum Erstellen und Starten eines Threads gibt Tatsächlich gibt es beim Multithreading eine Prozessklasse Process, mit der auch Daten im Speicher wie Listen usw. direkt gemeinsam genutzt werden können. , aber in Multiprozessen können Speicherdaten nicht gemeinsam genutzt werden. Daher muss eine separate Datenstruktur zur Verarbeitung gemeinsamer Daten in Multithreads verwendet werden. Die Datenfreigabe muss die Richtigkeit der Daten sicherstellen, daher muss etwas unternommen werden Bei mehreren Prozessen sollten Sperren selten in Betracht gezogen werden, da die Speicherinformationen des Prozesses nicht gemeinsam genutzt werden und interaktive Daten zwischen Prozessen eine spezielle Datenstruktur durchlaufen müssen. Bei mehreren Prozessen lautet der Hauptinhalt wie folgt:
2. Die Multiprozessklasse Process
Die Multiprozessklasse Process und die Multithread-Klasse Thread haben ähnliche Methoden. Die Schnittstellen der beiden sind im Grunde die gleichen. Siehe unten für Details:
#!/usr/bin/env python from multiprocessing import Process import os import time def func(name): print 'start a process' time.sleep(3) print 'the process parent id :',os.getppid() print 'the process id is :',os.getpid() if __name__ =='__main__': processes = [] for i in range(2): p = Process(target=func,args=(i,)) processes.append(p) for i in processes: i.start() print 'start all process' for i in processes: i.join() #pass print 'all sub process is done!'
Wie Sie im obigen Beispiel sehen können, Die API-Schnittstellen von Multiprozess und Multithread sind gleich. Der Erstellungsprozess wird angezeigt. Führen Sie dann „Start“ aus, um mit der Ausführung zu beginnen, treten Sie dann bei und warten Sie, bis der Prozess beendet ist.
In der auszuführenden Funktion werden die ID und die PID des Prozesses gedruckt, sodass Sie die ID-Nummern des übergeordneten Prozesses und des untergeordneten Prozesses sehen können. In Linu werden Prozesse hauptsächlich gegabelt. Beim Erstellen eines Prozesses können die ID-Nummern des übergeordneten Prozesses und des untergeordneten Prozesses abgefragt werden, die Thread-ID kann jedoch beim Multithreading nicht gefunden werden. Der Ausführungseffekt ist wie folgt:
start all process start a process start a process the process parent id : 8036 the process parent id : 8036 the process id is : 8037 the process id is : 8038 all sub process is done!
in Wenn Sie die ID im Betriebssystem abfragen, verwenden Sie am besten pstree, klar:
├─sshd(1508)─┬─sshd(2259)───bash(2261)───python(7520)─┬─python(7521) │ │ ├─python(7522) │ │ ├─python(7523) │ │ ├─python(7524) │ │ ├─python(7525) │ │ ├─python(7526) │ │ ├─python(7527) │ │ ├─python(7528) │ │ ├─python(7529) │ │ ├─python(7530) │ │ ├─python(7531) │ │ └─python(7532)
Beim Ausführen können Sie sehen, dass keine Join-Anweisung vorhanden ist , der Hauptprozess wartet nicht auf das Ende des untergeordneten Prozesses. Ja, er wird weiterhin ausgeführt und wartet dann auf die Ausführung des untergeordneten Prozesses.
Wie erhalte ich bei Verwendung mehrerer Prozesse den Rückgabewert mehrerer Prozesse? Dann habe ich den folgenden Code geschrieben:
#!/usr/bin/env python import multiprocessing class MyProcess(multiprocessing.Process): def __init__(self,name,func,args): super(MyProcess,self).__init__() self.name = name self.func = func self.args = args self.res = '' def run(self): self.res = self.func(*self.args) print self.name print self.res return (self.res,'kel') def func(name): print 'start process...' return name.upper() if __name__ == '__main__': processes = [] result = [] for i in range(3): p = MyProcess('process',func,('kel',)) processes.append(p) for i in processes: i.start() for i in processes: i.join() for i in processes: result.append(i.res) for i in result: print i
Versuchen Sie, einen Wert aus dem Ergebnis zurückzugeben, um den Rückgabewert des untergeordneten Prozesses im Hauptprozess zu erhalten. Allerdings gab es kein Ergebnis. Später dachte ich, dass sich die Prozesse den Speicher nicht teilen, sodass es offensichtlich nicht möglich ist, Listen zum Speichern von Daten zu verwenden. Die Interaktion zwischen Prozessen muss auf speziellen Datenstrukturen beruhen. Daher führt der obige Code nur den Prozess aus und kann den Rückgabewert des Prozesses nicht abrufen. Wenn der obige Code jedoch in einen Thread geändert wird, kann der Rückgabewert abgerufen werden.
3. Interprozess-Interaktionswarteschlange
Bei der Interaktion zwischen Prozessen können Sie zunächst dieselbe Warteschlangenstruktur im Multithreading verwenden Im Multiprozess müssen Sie die Warteschlange im Multiprozess verwenden. Der Code lautet wie folgt:
#!/usr/bin/env python import multiprocessing class MyProcess(multiprocessing.Process): def __init__(self,name,func,args): super(MyProcess,self).__init__() self.name = name self.func = func self.args = args self.res = '' def run(self): self.res = self.func(*self.args) def func(name,q): print 'start process...' q.put(name.upper()) if __name__ == '__main__': processes = [] q = multiprocessing.Queue() for i in range(3): p = MyProcess('process',func,('kel',q)) processes.append(p) for i in processes: i.start() for i in processes: i.join() while q.qsize() > 0: print q.get()
Tatsächlich ist dies eine Verbesserung des oben Gesagten Beispiel: Welcher andere Code wird verwendet? Die Hauptsache ist, die Warteschlange zum Speichern von Daten zu verwenden, damit der Zweck des Datenaustauschs zwischen Prozessen erreicht werden kann.
Was bei der Verwendung von Queue tatsächlich praktisch ist, ist der Socket, da darin immer noch das Senden und dann das Empfangen von Recv verwendet wird.
Bei der Durchführung einer Dateninteraktion interagiert der übergeordnete Prozess tatsächlich mit allen untergeordneten Prozessen. Es gibt grundsätzlich keine Interaktion zwischen allen untergeordneten Prozessen, es sei denn, es ist beispielsweise möglich, dass jeder Prozess in die Warteschlange gestellt wird Daten abrufen, zu diesem Zeitpunkt sollten jedoch Sperren in Betracht gezogen werden, da sonst die Daten verwechselt werden können.
4. Interaktion zwischen Prozessen Pipe
Pipe kann auch beim Datenaustausch zwischen Prozessen verwendet werden. Der Code lautet wie folgt:
#!/usr/bin/env python import multiprocessing class MyProcess(multiprocessing.Process): def __init__(self,name,func,args): super(MyProcess,self).__init__() self.name = name self.func = func self.args = args self.res = '' def run(self): self.res = self.func(*self.args) def func(name,q): print 'start process...' child_conn.send(name.upper()) if __name__ == '__main__': processes = [] parent_conn,child_conn = multiprocessing.Pipe() for i in range(3): p = MyProcess('process',func,('kel',child_conn)) processes.append(p) for i in processes: i.start() for i in processes: i.join() for i in processes: print parent_conn.recv()
Im obigen Code werden die beiden in Pipe zurückgegebenen Sockets hauptsächlich zum Senden und Empfangen von Daten verwendet. Im übergeordneten Prozess wird parent_conn und im untergeordneten Prozess verwendet. Daher sendet der untergeordnete Prozess Daten mit der Sendemethode und die Empfangsmethode recv
im übergeordneten Prozess Kann nicht mehr verwendet werden.
5. Prozesspool-Pool
Tatsächlich ist die Verwendung von Pools am bequemsten. Threading, es gibt keinen Pool.
在使用pool的时候,可以限制每次的进程数,也就是剩余的进程是在排队,而只有在设定的数量的进程在运行,在默认的情况下,进程是cpu的个数,也就是根据multiprocessing.cpu_count()得出的结果。
在poo中,有两个方法,一个是map一个是imap,其实这两方法超级方便,在执行结束之后,可以得到每个进程的返回结果,但是缺点就是每次的时候,只能有一个参数,也就是在执行的函数中,最多是只有一个参数的,否则,需要使用组合参数的方法,代码如下所示:
#!/usr/bin/env python import multiprocessing def func(name): print 'start process' return name.upper() if __name__ == '__main__': p = multiprocessing.Pool(5) print p.map(func,['kel','smile']) for i in p.imap(func,['kel','smile']): print i
在使用map的时候,直接返回的一个是一个list,从而这个list也就是函数执行的结果,而在imap中,返回的是一个由结果组成的迭代器,如果需要使用多个参数的话,那么估计需要*args,从而使用参数args。
在使用apply.async的时候,可以直接使用多个参数,如下所示:
#!/usr/bin/env python import multiprocessing import time def func(name): print 'start process' time.sleep(2) return name.upper() if __name__ == '__main__': results = [] p = multiprocessing.Pool(5) for i in range(7): res = p.apply_async(func,args=('kel',)) results.append(res) for i in results: print i.get(2.1)
在进行得到各个结果的时候,注意使用了一个list来进行append,要不然在得到结果get的时候会阻塞进程,从而将多进程编程了单进程,从而使用了一个list来存放相关的结果,在进行得到get数据的时候,可以设置超时时间,也就是get(timeout=5),这种设置。
总结:
在进行多进程编程的时候,注意进程之间的交互,在执行函数之后,如何得到执行函数的结果,可以使用特殊的数据结构,例如Queue或者Pipe或者其他,在使用pool的时候,可以直接得到结果,map和imap都是直接得到一个list和可迭代对象,而apply_async得到的结果需要用一个list装起来,然后得到每个结果。
以上这篇深入理解python多进程编程就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持PHP中文网。
更多Mehrprozessprogrammierung in Python verstehen相关文章请关注PHP中文网!