摘要:多線程對于爬蟲方面也可以表現(xiàn)出較好的性能。計算密集型就別想多線程了,一律多進程。所以同一時刻最大的并行線程數(shù)進程數(shù)的核數(shù)這條我的個人理解很模糊,參考吧多線程多線程有種通過的那種方式,非常普遍,此處就不寫了。
GIL的理解
GIL這個話題至今也是個爭議較多的,對于不用應用場景對線程的需求也就不同,說下我聽過的優(yōu)點: 1. 我沒有用過其他語言的多線程,所以無法比較什么,但是對于I/O而言,Python的線程還是比較高效的。 2. 有些第三方基于Python的框架和庫,比如Tensorflow等基于C/C plus plus重寫的Python線程機制。 3. 至于換成Cython編譯器解決GIL,這個只是聽過,沒用過。 4. Python多線程對于web、爬蟲方面也可以表現(xiàn)出較好的性能。 5. Python多進程是完好的,可以把資源消耗較少的非必要線程工作轉(zhuǎn)為多進程來工作。 6. 計算密集型就別想多線程了,一律多進程。 7. Python還有細粒度且高效的協(xié)程。 8. 如果有N核CPU,那么同時并行的進程數(shù)就是N,每個進程里面只有一個線程能搶到工作權(quán)限。 所以同一時刻最大的并行線程數(shù)=進程數(shù)=CPU的核數(shù)(這條我的個人理解很模糊,參考吧)多線程
多線程有2種通過start的那種方式,非常普遍,此處就不寫了。 新版線程池 future庫 是python3.2新出的功能(記住這個future) 方式1:(sublime運行后直接貼上來了) from time import sleep from concurrent.futures import ThreadPoolExecutor,as_completed,ALL_COMPLETED,wait executor = ThreadPoolExecutor(max_workers=10) # 初始化線程池10個坑 def f(): sleep(15) return 100 all_tasks = [executor.submit(f) for _ in range(10)] # 提交10個線程,全放池里執(zhí)行 # for per_thread in as_completed(all_tasks): # print(per_thread.result()) ---------# 注意上面,as_completed(all_tasks) 是等待future對象完成后才執(zhí)行主線程 ---------# 注意下面,wait和 as_completed() 的 作用一樣,就和普通版的join() 相似 for per_thread in all_tasks: print(per_thread.result()) wait(all_tasks, return_when=ALL_COMPLETED) # 還可以選FIRST_COMPLETED,待第一個完成后 print("主線程") 方式2: map多線程版 value_list = executor.map(func, list(range(10))) # 返回的直接是map后的序列 for value in value_list: print(value) 注意: 這個map方式,如果要傳多個參數(shù)就涉及到高階函數(shù)那節(jié)講的偏函數(shù)了。多進程
多進程有2種通過start的那種方式+普通進程池,同樣非常普遍,此處就不寫了,自己百度一下。 新版進程池 同樣是和上面用一樣的future庫,驚不驚喜。(可以看出好的程序要向著統(tǒng)一封裝的方向優(yōu)化) 也許你會驚訝,因為只把thread單詞改為processing就是進程池版本了,就是這么簡單!!!!! from time import sleep import multiprocessing from concurrent.futures import ProcessPoolExecutor,as_completed,ALL_COMPLETED,wait executor = ProcessPoolExecutor(max_workers=multiprocessing.cpu_count()) def f(): sleep(15) return 100 if __name__ == "__main__": # 這句要加 all_tasks = [executor.submit(f) for _ in range(multiprocessing.cpu_count())] for per_thread in as_completed(all_tasks): print(per_thread.result()) # for per_thread in all_tasks: # print(per_thread.result()) # wait(all_tasks, return_when=ALL_COMPLETED) print("主進程") # 這就是 futures 模塊 設計思想的魅力多協(xié)程
前言: 也許你記得,函數(shù)用到 yield 來代替 return 就變成了 生成器。其特點是代碼片段斷點式執(zhí)行。 如果有多個yield, 就可以自己用程序來切換執(zhí)行程序。(這就是協(xié)程的特點) 推薦:(學習中。。。) 此筆者寫的很好: https://juejin.im/post/5ccf0d18e51d453b557dc340
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/43848.html
摘要:解釋就相當于把每個序列元素的每一個單獨用一個管道函數(shù)處理,再把他們按順序組合成一個新可迭代對象注意這個管道函數(shù)只能是單參數(shù)函數(shù),如果想傳遞多個參數(shù)怎么辦使用偏函數(shù)怕有些人看不懂,這里就不用了,而是用普通函數(shù)定義方式固定值固定值固定值固定值固 map In [25]: list(map(lambda a:a**2, [1,2,3,4])) Out[25]: [1, 4, 9, 16] 解...
摘要:不要疑惑,告訴你答案這個代表正負號的正。雖然一點技術含量沒有,但是你要懂序列也許叫可迭代對象更為合適,但是我喜歡叫序列。 數(shù)據(jù)結(jié)構(gòu) 可變類型與不可變類型(重頭戲) 基操: 可變類型:[], {} # 可增刪改 查 不可變類型: int float str () # 無法增刪改, 只可查 升操: + 與...
摘要:類的繼承類繼承有三種調(diào)用方式,其實是有區(qū)別的,聽我慢慢道來第一種父類方法參數(shù)直接調(diào)用第二種方法參數(shù)直接調(diào)用在誰的類下調(diào)用,就找此類對應的下一個就是要繼承的第三種方法參數(shù)找類名對應的的下一個,就是繼承的,一般寫本身的類名上下文管理器上下文管理 類的繼承 類繼承有三種調(diào)用方式,其實是 有區(qū)別 的,聽我慢慢道來 class A: def say(self, name): ...
摘要:也就是給原函數(shù)加個外殼。類裝飾填充了啊我是原函數(shù)類裝飾填充了啊我是原函數(shù)說明后面關于類的裝飾器如果理解困難當做了解即可,用的也少。 可迭代對象、生成器、迭代器三者的關系 1. 迭代器一定是可迭代對象 2. 生成器是迭代器的一種 3. 可迭代對象:必須實現(xiàn) __iter__方法 4. 迭代器:必須實現(xiàn) __iter__方法 和 __next__ 方法 5. 生成器:必須實現(xiàn) __it...
預編譯 import re re1 = re.compile(r元字符 組成的正則規(guī)則) # 元字符下面會說 re1.方法() # 方法下邊也會說 元字符: 表示普通字符: . # 除了 外 都可以匹配的到 d # 只匹配 純數(shù)字 0-9 D # 和 d相反, 除了數(shù)字全都匹配 ...
閱讀 1587·2021-11-22 15:33
閱讀 1728·2021-11-15 18:01
閱讀 664·2021-10-09 09:43
閱讀 2604·2021-09-22 16:03
閱讀 758·2021-09-03 10:28
閱讀 3550·2021-08-11 10:22
閱讀 2718·2019-08-30 15:54
閱讀 1761·2019-08-30 14:21