HandlerInterceptor源碼 ##3種方法: preHandle:攔截於請求剛進入時,進行判斷,需要boolean返回值,如果返回true將繼續執行,如果返回false,將不進行執行。一般用於登錄校驗。 postHandle:攔截於方法成功返回後,視圖渲染前,可以對modelAndVie ...
引言
multiprocessing是一個用於產生多進程的包,與threading模塊的API類似。multiprocessing既可以實現本地的多進程,也可以實現遠程的多進程。通過使用多個子進程而非線程可以繞開Python的全局解釋器鎖(GIL),同時允許在多種系統平臺使用。
1. Process 模塊
1.1 Process介紹
Process模塊是一個創建進程的模塊,可以通過Process直接創建進程。
multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None) """ 參數介紹: 1. group預設為None(目前未使用) 2. target代表調用對象,即子進程執行的任務 3. name為進程名稱 4. args調用對象的位置參數元組,args=(value1, value2, ...) 5. kwargs調用對象的字典,kwargs={key1:value1, key2:value2, ...}
6. daemon表示進程是否為守護進程,布爾值
方法介紹:
Process.start() 啟動進程,並調用子進程中的run()方法
Process.run() 進程啟動時運行的方法,在自定義時必須要實現該方法
Process.terminate() 強制終止進程,不進行清理操作,如果Process創建了子進程,會導致該進程變成僵屍進程
Process.join() 阻塞進程使主進程等待該進程終止
Process.kill() 與terminate()相同
Process.is_alive() 判斷進程是否還存活,如果存活,返回True
Process.close() 關閉進程對象,並清理資源,如果進程仍在運行則返回錯誤
"""
註意:
- 在Windows中,由於沒有fork(Linux中創建進程的機制),在創建進程的時候會import啟動該文件,而在import文件的時候又會再次運行整個文件,如果把Process()放在 if __name__ == '__main__' 判斷之外,則Process()在被import的時候也會被運行,導致無限遞歸創建子進程導致報錯,所以在Windows系統下,必須把Process()放在 if __name__ == '__main__' 的判斷保護之下。
- 在子進程中不能使用input,因為輸入台只顯示在主進程中,故如果在子進程中使用input,會導致報錯。
1.2 Process實例
from multiprocessing import Process def main(name): print(f'{name}: Hello World') if __name__ == '__main__': # 創建子進程 p = Process(target=main, args=('LovefishO',)) # 開始進程 p.start() # 阻塞進程 p.join()例子
1.3 Process類實現
from multiprocessing import Process class NewProcess(Process): def __init__(self, name): # 執行父類的init() super().__init__() # 創建新參數 self.name = name # 在自定義Process類時,必須實現run()方法 def run(self): print(f'{self.name}: Hello World') if __name__ == '__main__': # 創建一個新的子進程,並傳入參數 np = NewProcess('LovefishO') # 開始子進程 np.start() # 加入阻塞,保證主進程在子進程之後結束 np.join() print('主進程結束') # LovefishO: Hello World # 主進程結束
1.4 守護進程
正常情況下,當子進程和主進程都結束時,程式才會結束。但是當我們需要在主進程結束時,由該主進程創建的子進程也必須跟著結束時,就需要使用守護進程。當一個子進程為守護進程時,在主進程結束時,該子進程也會跟著結束。
from multiprocessing import Process def main(name): print(f'{name}: Hello World') if __name__ == '__main__': # 創建守護進程, 設置daemon = True p = Process(target=main, daemon=True, args=('LovefishO',)) # 開始進程 p.start() # 阻塞進程 p.join()
2. Pool 模塊
2.1 Pool介紹
Pool模塊控制著一個進程池,池中是可以執行很多任務的進程
multiprocessing.Pool(processes=None, initializer=None, initargs=(), maxtasksperchild=None, context=None) """ 參數介紹: processes: 設置要使用的進程數量,如果 processes 為 None,則使用 os.cpu_count() 返回的值
initializer: 是每個工作進程啟動時要執行的可調用對象,預設為None maxtasksperchild: 工作進程退出之前可以完成的任務數,完成後用一個新的工作進程來替代原進程,為了釋放閑置資源 context: 可被用於指定啟動的工作進程的上下文 """
2.2 Pool中分派任務的方式
-
apply(func[, args[, kwds]])方法是阻塞,意味著當前的進程沒有執行完的話,後續的進程需要等待該進程執行結束才能執行,實際上該方法是串列。
-
apply_async(func[, args[, kwds[, callback[, error_callback]]]])方法是非同步非阻塞的,意味著不用等待當前進程執行完成,即可根據系統的調度切換進程,該方法是並行。
-
map(func, iterable[, chunksize])方法將iterable對象分成一些塊,作為單獨的任務提交給進程池。 這些塊的(近似)大小可以通過將chunksize設置為正整數來指定, 並且該方法是阻塞的。如果可迭代對象很多時,會消耗較大的記憶體,可以考慮使用imap或imap_unordered。
-
map_async(func, iterable[, chunksize[, callback[, error_callback]]])方法是map的變種,是非阻塞的。
-
imap(func, iterable[, chunksize])該方法和map一樣,只不過該方法適用於對大量數據的遍歷,返回的結果順序和輸入相同。
-
imap_unordered(func, iterable[, chunksize])與imap()一樣,只不過輸出的順序是任意的
2.3 Pool實例
from multiprocessing import Pool def main(name, num): print(f'{num} {name}: Hello World') if __name__ == '__main__': # 創建進程池 p = Pool() for i in range(5): p.apply(func=main, args=('LovefishO', i, )) # 關閉進程池 p.close() # 阻塞進程, 等待子進程執行結束 p.join() print('主進程結束') # 0 LovefishO: Hello World # 1 LovefishO: Hello World # 2 LovefishO: Hello World # 3 LovefishO: Hello World # 4 LovefishO: Hello World # 主進程結束Pool例子
3. Queue 模塊
3.1 Queue介紹
由於進程彼此之間互相隔離,要實現進程間通信,multiprocessing提供了兩種形式:隊列(queue)和管道。隊列可以簡單的理解為一種特殊的列表,可以設置固定的長度,從左邊插入數據,從右邊獲取數據,並滿足先進先出。並且隊列時進程安全的,即同一時刻只有一個進程能夠對隊列進行操作。
multiprocessing.Queue(maxsize) """ 參數介紹: maxsize:設置隊列長度 方法介紹: qsize():返回隊列長度,該結果是不可靠的,因為在使用該方法時,隊列中的數據仍在進行刪除增加 empty():如果隊列為空,則返回True,反之亦然,該狀態不可靠 full():如果隊列滿了,則返回True,反之亦然,該狀態不可靠 put(obj[, block[, timeout]]):將obj放入隊列 get([block[, timeout]]):從隊列中取出並返回對象
close(): 當前進程不會在隊列中放入對象 """
3.2 Queue實例
from multiprocessing import Process, Queue def product(queue, num): # 把obj插入隊列 queue.put(num) print(f'Product {num}') def consumer(queue): # 從隊列中獲取數據 temp = queue.get() print(f'consumer consumed {temp} product') if __name__ == '__main__': # 創建隊列 q = Queue() # 生產商品 for i in range(5): p1 = Process(target=product, args=(q, i, )) p1.start() # 消費生產的商品 for i in range(5): p2 = Process(target=consumer, args=(q,)) p2.start()Queue例子
註意:
- 在使用隊列時(Queue)如果要使用進程池則不能使用multiprocessing.Pool,而是應用使用multiprocessing.Manager().Pool()
3.3 Queue + Pool實例
import multiprocessing def product(queue, num): # 把obj插入隊列 queue.put(num) print(f'Product {num}') def consumer(queue): # 從隊列中獲取obj num = queue.get() print(f'consumer consumed {num} product') if __name__ == '__main__': # 創建隊列 q = multiprocessing.Manager().Queue() # 創建進程池 p = multiprocessing.Pool() # 生產商品 for i in range(5): p.apply(func=product, args=(q, i,)) # 消費生產的商品 for i in range(5): p.apply(func=consumer, args=(q,)) # 關閉進程池 p.close() # 阻塞進程 p.join() print('主進程結束') # Product 0 # Product 1 # Product 2 # Product 3 # Product 4 # consumer consumed 0 product # consumer consumed 1 product # consumer consumed 2 product # consumer consumed 3 product # consumer consumed 4 product # 主進程結束Queue + Pool例子
4. Reference
本文來自博客園,作者:LoveFishO,轉載請註明原文鏈接:https://www.cnblogs.com/lovefisho/p/16202006.html