標籤:簡易 recv log sim sem 沒有 詳解 inux join
多進程multiprocess模組
multiprocessing is a package that supports spawning processes using an API similar to the threading module. The multiprocessing package offers both local and remote concurrency, effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads. Due to this, the multiprocessing module allows the programmer to fully leverage multiple processors on a given machine. It runs on both Unix and Windows.
這個模組的文法結構與threading模組基本相似。
尋找到一個多進程的部落格串連:https://www.cnblogs.com/Mr-Murray/p/9026955.html
from multiprocessing import Processimport timeimport osdef info(): print("\033[35;1mThe time is %s\033[0m" % time.ctime()) print("The parent is %s; The Child process is %s" % (os.getppid(), os.getpid()))if __name__ == "__main__": for i in range(10): p = Process(target=info) p.start() p.join()
這段代碼和之前用threading模組建立的多線程並沒有任何的區別,但是如果在windows系統上執行時,必須加上if __name__ == "__main__":語句,原因如下:
在Windows作業系統中由於沒有fork(linux作業系統中建立進程的機制),在建立子進程的時候會自動 import 啟動它的這個檔案,
而在 import 的時候又執行了整個檔案。因此如果將process()直接寫在檔案中就會無限遞迴建立子進程報錯。所以必須把建立子
進程的部分使用if __name__ ==‘__main__’ 判斷保護起來,import 的時候 ,就不會遞迴運行了。
以執行個體化的方式產生進程:
import os, timefrom multiprocessing import Processclass Myprocess(Process): def __init__(self): super(Myprocess, self).__init__() def run(self): print("\033[35;1mThe time is %s\033[0m" % time.ctime()) print("The parent is %s; The Child process is %s" % (os.getppid(), os.getpid()))if __name__ == "__main__": p = Myprocess() p.start()
#在調用p.start的時候,會自動執行類中的run方法,run方法是必不可少的。和threading類中的Thread中的run方法一樣。
進程中的守護進程和threading模組中的守護線程是同一個意思,主進程結束的時候,子進程也會隨之結束。
import os, timefrom multiprocessing import Processdef fun1(): print("starting %s".center(50,"-") % time.ctime()) time.sleep(3) print("Stopping %s".center(50,"-") % time.ctime())if __name__ == "__main__": p = Process(target=fun1) p.daemon = True p.start() time.sleep(1)--------------------------------------------------------------------------子進程中是要執行3s的,但主進程中只執行了1s,設定了守護進程之後,主進程結束,不管子進程的狀態,子進程都要退出
利用多進程實現簡易的socket並發串連。
server端代碼:import socket, timefrom multiprocessing import Processdef handle(conn,addr): print("The connection is from %s at %s port" % addr) conn.send(b"Hello world") data = conn.recv(1024) conn.send(data)if __name__ == "__main__": HOST = "localhost" PORT = 51423 ADDR = (HOST, PORT) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(ADDR) s.listen(5) while True: conn, addr = s.accept() p = Process(target=handle, args=(conn,addr)) # 進程間的資料是不共用的,因此需要把coon作為參數傳遞 p.start() s.close()client端代碼:import socketHOST = "localhost"PORT = 51423ADDR = (HOST, PORT)s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect(ADDR)data = s.recv(1024)print(data.decode())while True: info = input(">>>: ") s.send(info.encode()) data = s.recv(1024) print(data.decode())
注意:
進程之間的資料是彼此之間不能互相訪問的,因此conn必須作為參數傳遞。
進程之間的通訊該怎麼做?
進程中的隊列和管道:
from multiprocessing import Process, Queuefrom time import sleepimport random# 利用進程寫一個產生消費者模型,# 產生者向隊列插入一個隨機數,消費者取出隊列中的一個數值def productor(q): while True: sleep(0.3) print("store an num") q.put(random.randint(1,100))def consumer(q): while True: sleep(0.2) print("Getting an num") q.get()if __name__ == "__main__": q = Queue() proc1 = Process(target=productor, args=(q,)) proc2 = Process(target=consumer, args=(q,)) proc1.start() proc2.start()
這隻是一個簡易模型,來說明隊列在進程之間的通訊。
這裡的隊列用法和線程中隊列用法基本相同,只是一個用於進程通訊,一個用於線程通訊。
管道
管道的簡單實用:
from multiprocessing import Process, Pipedef f(conn): conn.send("Hello world") conn.close()if __name__ == ‘__main__‘: parent_conn, child_conn = Pipe() p = Process(target=f, args=(child_conn,)) p.start() print(parent_conn.recv()) p.join()manager
Manager()返回的manager對象控制了一個server進程,此進程包含的python對象可以被其他的進程通過proxies來訪問。從而達到多進程間資料通訊且安全。
A manager object returned by Manager() controls a server process which holds Python objects and allows other processes to manipulate them using proxies.
A manager returned by Manager() will support types list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value and Array.
一個簡單實用的執行個體:
from multiprocessing import Process, Managerimport randomdef f(list): list.append(random.randint(0,100)) print(list)if __name__ == "__main__": p_list = [] with Manager() as manager: l = manager.list() for i in range(10): p = Process(target=f,args=(l,)) p.start() p_list.append(p) for res in p_list: res.join()
每一個進程給列表中添加一個資料,執行結果如下:
[95]
[95, 25]
[95, 25, 31]
[95, 25, 31, 70]
[95, 25, 31, 70, 9]
[95, 25, 31, 70, 9, 17]
[95, 25, 31, 70, 9, 17, 96]
[95, 25, 31, 70, 9, 17, 96, 71]
[95, 25, 31, 70, 9, 17, 96, 71, 96]
[95, 25, 31, 70, 9, 17, 96, 71, 96, 3]
進程池:
進程池內部維護一個進程式列,當使用時,則去進程池中擷取一個進程,如果進程池序列中沒有可供使用的進進程,那麼程式就會等待,直到進程池中有可用進程為止。
from multiprocessing import Process, Poolimport timedef Foo(i): time.sleep(2) return i + 100def Bar(arg): print(‘-->exec done:‘, arg)if __name__ == "__main__": pool = Pool(5) for i in range(10): pool.apply_async(func=Foo, args=(i,), callback=Bar) # pool.apply(func=Foo, args=(i,)) print(‘end‘) pool.close() pool.join()
注意:其中在調用apply_async時候使用了callback回呼函數
進程池詳解,看到的一片博文:https://www.cnblogs.com/qiangyuge/p/7455814.html
python進程編程