python 基礎(一) multiprocessing庫 進程 線程 併發 並行 args kwargs

這裏雜亂的介紹window系統下 多進程相關庫multiprocess 進程 線程 併發 並行概念 初步有個大致的印象 IDE:Jetbrain pycharm 2019
python基礎系列 正在持續更新中:)

multiprocess定義 + 更改快捷鍵 + 查詢字段定義

首先我們得找到其定義(definition),選中一個詞然後在View-Quick Definition就能夠實現
在這裏插入圖片描述
建議可以更改快捷鍵爲Ctrl+D,如下圖:File-Settings:
在這裏插入圖片描述
接下來 Ctrl+D 查詢multiprocess 似乎因爲版本關係,原來直接在multiprocess能看到的class process定義沒了,而是再找Baseprocess:

class BaseProcess:
    name: str
    daemon: bool
    authkey: bytes
    def __init__(
        self,
        group: None = ...,
        target: Optional[Callable[..., Any]] = ...,
        name: Optional[str] = ...,
        args: Tuple[Any, ...] = ...,
        kwargs: Mapping[str, Any] = ...,
        *,
        daemon: Optional[bool] = ...,
    ) -> None: ...
    def run(self) -> None: ...
    def start(self) -> None: ...
    def terminate(self) -> None: ...

可見process有幾個屬性:

名稱 說明 中文
target Callable 可被調用的目標
name str 名字 字符串形式
args Tuple 元祖形式的參數
kwargs Mapping str 鍵值對形式的參數

還有幾個方法 run(運行) start(開啓) terminate(終止)

下面我們先理解一下args kwargs

args kwargs

*args = arguments 參數(形參)的意思
**kwargs = key word arguments 所以 是“鍵值參數”?
No, 鍵值參數,還記得字典dict的鍵值對嘛,沒錯,這個kwargs只接受鍵值對傳入,其他的事不關己高高掛起,同樣args也不會越俎代庖,也只接受 多個 普通的單值參數比如字符串,數字,etc
來試試下面的例子:

def ryan_test(arg,*args,**kwargs):
    print arg
    print args
    print kwargs
 
Ryan_test(1,2,3,d='4',e=5)

一個蘿蔔一個坑,形參arg就對應第一個傳入參數1,
鍵值對(keywords) d=‘4’,e=5 被**kwargs承包了,
意味着只有*args能夠收拾剩下的爛攤子——數字 2,3,
注意是args 帶s意味着複數,意思多個單值參數

輸出結果:
1
(2, 3)
{'e': 5, 'd': '4'}

我們再來看個案例:python的dict類構造函數是怎麼工作的:
myDICT = dict(a=1,b=2,c=3) 這個能夠生成值爲{a=1,b=2,c=3}的一個字典
其實就可以用**kwargs實現:

def ryan_dict(**kwargs):
    return kwargs
    
print ryan_dict(a=1,b=2,c=3) == {'a':1, 'b':2, 'c':3}

你可以封裝成一個類,我比較懶就不管了:)

multiprocess使用

我們利用multiprocess的Process對象 創建 進程
創建進程的類
Process([group [, target [, name [, args [, kwargs]]]]]),由該類實例化得到的對象,表示一個子進程中的任務(尚未啓動)
創建子進程需要傳入參數 比如我就
Process(target=task_1, name="任務1",args=(1,'Ryan',))
意思 執行任務 task_1函數,子進程名字爲“任務1”,傳入參數(1,‘Ryan’)。

我們直接來看一個栗子 就理解了:

#-*- utf-8 -*-
from time import sleep
import os
from multiprocessing import Process


def task_1(second, name):
    while True:
        sleep(second)
        print("TASK " + name + "-- "+str(os.getpid()),"--",str(os.getppid()))

def task_2(second, name):
    while True:
        sleep(second)
        print("TASK " + name + "-- "+str(os.getpid()),"--",str(os.getppid()))


if __name__ == '__main__':
    print(os.getpid())
    p1 = Process(target=task_1, name="任務1",args=(1,'Ryan',))
    p1.start()

    p2 = Process(target=task_2, name="任務2",args=(2,'sst',))
    p2.start()

這裏解釋一下 task_1 task_2 就是子進程,因爲用了start()函數,所以是作爲子進程(ChildProcess) 我們利用getpid()函數獲得進程的識別碼ID PID = process ID
可以看到
Ryan 子進程 PID = 9796
sst 子進程PID = 2412
那1816就是父進程(parent process)getppid()也就是:get parent pid,從而 獲得其pid

在這裏插入圖片描述
打開任務管理器 taskmgr 可見我們兩個子進程 一個父進程
識別碼

run start terminate

start() 啓動我們Process創建的實例——一個進程,然後會默認調用run(),run()只負責執行屬性target中的函數,其他的不管,意味着使用它不能實現進程,以及單核併發,或者多核並行邏輯
總之 使用start()就對了
terminate() 就是用於終止子進程的,類似的函數還有kill()

進程 線程 多任務

進程可以說是線程(Threadings, thread有織毛衣的的意思)的爸爸 集合。進程,就像一個包含很多線程的大家庭。線程就是兄弟姐妹,共有一個進程爸爸。兄弟姐妹間聊天比較暢通無阻,所以線程間是可以直接信息交流的,甚至可以創建、撤銷新的進程,而且共享系統資源(共享一個家),自己只能擁有運行必須的最小資源(比如自己的一個小房間),所以線程佔用資源很少。當然,每家每戶都有一塊地,這就是系統os爲進程開闢的內存空間,所以每開一個進程,就要求系統分配一份空間。
家庭雖然是公用的,但是總有公共部分,譬如廁所,一次可能只能有一個人在裏面使用。線程也是如此,常常是併發執行concurrent,所以先後不重要(代碼放的位置先後),因爲是輪詢的,總會輪到你。

但是進程間就是一個個分立的家庭了,資源不共享(你家和別家,不在一個屋檐下,資源不太可能共享),另外,信息共享也不容易,所以不是直接信息傳遞,往往通過pipe等間接傳信息的

我們想實現多任務 就有兩種方式了:
多進程 計算密集型 佔用內存等系統資源
多線程 耗時操作型 適用於下載 爬蟲 或者更廣泛的:文件IO等耗時工作
具體爲什麼 請看python 基礎(三) 線程 Threading GIL 線程同步

任務調度 併發 並行

CPU的任務調度( task dispatcher) 這裏記一下dispatch這個單詞:patch 斑點,星星點點就好像是撒出去一樣,派發出去一樣,所以dispatch 派發 派遣。CPU派遣調度人,就是dispatcher
那麼假設我們只有單核的CPU,我們需要實現多任務同時執行,然而並不可能,因爲只有一個處理器CPU,於是就可以花式調度任務——快速切換,比如10us執行任務1,10us執行task2,我們肉眼看來就好像是同時進行的。
那麼 單核CPU進行這項花式操作,就是併發(concurrenty, i.e con-current-y)
如果多核呢?目前撐死也就16核,任務數量還是遠多於核的數量,但比起單核還是輕鬆一些——比如有4核,那麼4個任務(task1,2,3,4)是真正 同時進行的
核1 10us執行task1,10us執行task5
核2 10us執行task2,10us執行task6
核3 10us執行task3,10us執行task7
核4 10us執行task4,10us執行task8
這樣的稱爲 並行(Parallelism,i.e Parallel-ism)

下一站將會更加硬核 深入理解Process 當然還是採用multiprocess庫 盡請關注:
python 基礎(二)阻塞 非阻塞 同步 異步

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章