python高級(jí) 6 進(jìn)程

進(jìn)程、進(jìn)程的使用、進(jìn)程注意點(diǎn)、進(jìn)程間通信-Queue、進(jìn)程池Pool、進(jìn)程與線程對(duì)比、文件夾拷貝器-多任務(wù)

1.進(jìn)程介紹

多進(jìn)程本質(zhì)是創(chuàng)建一個(gè)進(jìn)程默認(rèn)創(chuàng)建一個(gè)線程,任務(wù)本身是由線程完成的。多進(jìn)程可以處理多任務(wù),但是每創(chuàng)建一個(gè)進(jìn)程都要向系統(tǒng)索要運(yùn)行資源,相比線程來(lái)說(shuō)資源占用比較多成本比較大

<1>進(jìn)程的概念

進(jìn)程:通俗理解一個(gè)運(yùn)行的程序或者軟件,進(jìn)程是操作系統(tǒng)資源分配的基本單位。

注意:一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程,多進(jìn)程可以完成多任務(wù).

<2>進(jìn)程的狀態(tài)

工作中,任務(wù)數(shù)往往大于cpu的核數(shù),即一定有一些任務(wù)正在執(zhí)行,而另外一些任務(wù)在等待cpu進(jìn)行執(zhí)行,因此導(dǎo)致了有不同的狀態(tài)

? 就緒態(tài):運(yùn)行的條件都已經(jīng)滿足,正在等待cpu執(zhí)行

? 執(zhí)行態(tài):cpu正在執(zhí)行其功能

? 等待態(tài):等待某些條件滿足,例如一個(gè)程序sleep了,此時(shí)就處于等待態(tài)

小結(jié):

一個(gè)進(jìn)程默認(rèn)有一個(gè)線程,進(jìn)程里面可以創(chuàng)建線程,線程是依附在進(jìn)程里面的,沒(méi)有進(jìn)程就沒(méi)有線程。

2.進(jìn)程的使用

<1>多進(jìn)程完成多任務(wù)

? 導(dǎo)入進(jìn)程模塊

import multiprocessing

<2>Process進(jìn)程類(lèi)的語(yǔ)法結(jié)構(gòu)如下:

Process([group [, target [, name [, args [, kwargs]]]]])

? group:指定進(jìn)程組,目前只能使用None

? target:執(zhí)行的目標(biāo)任務(wù)名

? name:進(jìn)程名字

? args:以元組方式給執(zhí)行任務(wù)傳參

? kwargs:以字典方式給執(zhí)行任務(wù)傳參

Process創(chuàng)建的實(shí)例對(duì)象的常用方法:

? start():?jiǎn)?dòng)子進(jìn)程實(shí)例(創(chuàng)建子進(jìn)程)

? join([timeout]):是否等待子進(jìn)程執(zhí)行結(jié)束,或等待多少秒

? terminate():不管任務(wù)是否完成,立即終止子進(jìn)程

Process創(chuàng)建的實(shí)例對(duì)象的常用屬性:

? name:當(dāng)前進(jìn)程的別名,默認(rèn)為Process-N,N為從1開(kāi)始遞增的整數(shù)

? pid:當(dāng)前進(jìn)程的pid(進(jìn)程號(hào))

<3>多進(jìn)程完成多任務(wù)代碼

import multiprocessing

import time

def run_proc():

? ? """子進(jìn)程要執(zhí)行的代碼"""

? ? while True:

? ? ? ? print("----2----")

? ? ? ? time.sleep(1)

if __name__=='__main__':

? ? # 創(chuàng)建子進(jìn)程

? ? sub_process = multiprocessing.Process(target=run_proc)

? ? # 啟動(dòng)子進(jìn)程

? ? sub_process.start()

? ? while True:

? ? ? ? print("----1----")

? ? ? ? time.sleep(1)

<4>獲取當(dāng)前進(jìn)程、當(dāng)前進(jìn)程pid、父進(jìn)程pid(paternal pid)、殺死對(duì)應(yīng)的進(jìn)程

? 獲取當(dāng)前進(jìn)程

? ? ? multiprocessing.current_process()

? 獲取當(dāng)前進(jìn)程的編號(hào)

? ? ? multiprocessing.current_process().pid

? ? ? os.getpid()

? 獲取父進(jìn)程的編號(hào)

? ? ? os.getppid()

? 根據(jù)進(jìn)程編號(hào)殺死對(duì)應(yīng)的進(jìn)程

? ? ? os.kill(os.getpid(), 9)

import multiprocessing

import time

import os

def work():

? ? # 查看當(dāng)前進(jìn)程

? ? current_process = multiprocessing.current_process()

? ? print("work:", current_process)

? ? # 獲取當(dāng)前進(jìn)程的編號(hào)

? ? print("work進(jìn)程編號(hào):", current_process.pid, os.getpid())

? ? # 獲取父進(jìn)程的編號(hào)

? ? print("work父進(jìn)程的編號(hào):", os.getppid())

? ? for i in range(10):

? ? ? ? print("工作中....")

? ? ? ? time.sleep(0.2)

? ? ? ? # 擴(kuò)展: 根據(jù)進(jìn)程編號(hào)殺死對(duì)應(yīng)的進(jìn)程

? ? ? ? os.kill(os.getpid(), 9)

if __name__ == '__main__':

? ? # 查看當(dāng)前進(jìn)程

? ? current_process = multiprocessing.current_process()

? ? print("main:", current_process)

? ? # 獲取當(dāng)前進(jìn)程的編號(hào)

? ? print("main進(jìn)程的編號(hào):", current_process.pid)

? ? # 創(chuàng)建子進(jìn)程

? ? sub_process = multiprocessing.Process(target=work)

? ? # 啟動(dòng)進(jìn)程

? ? sub_process.start()

? ? # 主進(jìn)程執(zhí)行打印信息操作

? ? for i in range(20):

? ? ? ? print("我在主進(jìn)程中執(zhí)行...")

? ? ? ? time.sleep(0.2)

<5>給子進(jìn)程指定的函數(shù)傳遞參數(shù)

import multiprocessing

# 顯示人員信息

def show_info(name, age):

? ? print(name, age)

if __name__ == '__main__':

? ? # 創(chuàng)建子進(jìn)程

? ? # 1. group:進(jìn)程組,目前必須使用None,一般不用設(shè)置

? ? # 2. target:執(zhí)行目標(biāo)函數(shù)

? ? # 3. name: 進(jìn)程名稱(chēng)

? ? # 4. args: 以元組方式給函數(shù)傳參

? ? # 5. kwargs: 以字典方式給函數(shù)傳參

? ? sub_process = multiprocessing.Process(target=show_info, name="myprocess", args=("古力娜扎", 18))

? ? # 啟動(dòng)進(jìn)程

? ? sub_process.start()

? ? # sub_process = multiprocessing.Process(target=show_info, name="myprocess", kwargs={"name": "貂蟬", "age": 20})

? ? #

? ? # # 啟動(dòng)進(jìn)程

? ? # sub_process.start()

3.進(jìn)程注意點(diǎn)

<1>進(jìn)程之間不共享全局變量

import multiprocessing

import time

# 定義全局變量

my_list = list()

# 寫(xiě)入數(shù)據(jù)

def write_data():

? ? for i in range(5):

? ? ? ? my_list.append(i)

? ? ? ? time.sleep(0.2)

? ? print("write_data:", my_list)

# 讀取數(shù)據(jù)

def read_data():

? ? print(my_list)

if __name__ == '__main__':

? ? # 創(chuàng)建寫(xiě)入數(shù)據(jù)的進(jìn)程

? ? write_process = multiprocessing.Process(target=write_data)

? ? read_process = multiprocessing.Process(target=read_data)

? ? write_process.start()

? ? # 主進(jìn)程等待寫(xiě)入進(jìn)程執(zhí)行完成以后代碼 再繼續(xù)往下執(zhí)行

? ? write_process.join()

? ? read_process.start()

執(zhí)行結(jié)果:

write_data: [0, 1, 2, 3, 4]

read_data: []

注意:

創(chuàng)建子進(jìn)程其實(shí)是對(duì)主進(jìn)程(除了main方法程序入口以外的,Windows如果創(chuàng)建子進(jìn)程不用main程序入口會(huì)無(wú)限循環(huán)創(chuàng)建進(jìn)程導(dǎo)致程序報(bào)錯(cuò))所有資源進(jìn)行拷貝,進(jìn)程之間相互獨(dú)立,訪問(wèn)的全局變量不是同一個(gè),所以進(jìn)程之間不共享全局變量

多進(jìn)程之間可能出現(xiàn)相同名字的全局變量,但是不是同一個(gè)全局變量,是不同的全局變量,只不過(guò)名字相同而已

<2>主進(jìn)程會(huì)等待所有的子進(jìn)程執(zhí)行完成程序再退出

import multiprocessing

import time

# 測(cè)試子進(jìn)程是否執(zhí)行完成以后主進(jìn)程才能退出

def work():

? ? for i in range(10):

? ? ? ? print("工作中...")

? ? ? ? time.sleep(0.2)

if __name__ == '__main__':

? ? # 創(chuàng)建子進(jìn)程

? ? work_process = multiprocessing.Process(target=work)

? ? work_process.start()

? ? # 讓主進(jìn)程等待1秒鐘

? ? time.sleep(1)

? ? print("主進(jìn)程執(zhí)行完成了啦")

總結(jié): 主進(jìn)程會(huì)等待所有的子進(jìn)程執(zhí)行完成以后程序再退出

<3>銷(xiāo)毀子進(jìn)程的代碼

設(shè)置守護(hù)主進(jìn)程,主進(jìn)程退出后子進(jìn)程直接銷(xiāo)毀,不再執(zhí)行子進(jìn)程中的代碼

子進(jìn)程名.daemon = True

讓子進(jìn)程直接銷(xiāo)毀,表示終止執(zhí)行, 主進(jìn)程退出之前,把所有的子進(jìn)程直接銷(xiāo)毀就可以了

子進(jìn)程名.terminate()

import multiprocessing

import time

# 測(cè)試子進(jìn)程是否執(zhí)行完成以后主進(jìn)程才能退出

def work():

? ? for i in range(10):

? ? ? ? print("工作中...")

? ? ? ? time.sleep(0.2)

if __name__ == '__main__':

? ? # 創(chuàng)建子進(jìn)程

? ? work_process = multiprocessing.Process(target=work)

? ? # 設(shè)置守護(hù)主進(jìn)程,主進(jìn)程退出后子進(jìn)程直接銷(xiāo)毀,不再執(zhí)行子進(jìn)程中的代碼

? ? # work_process.daemon = True

? ? work_process.start()

? ? # 讓主進(jìn)程等待1秒鐘

? ? time.sleep(1)

? ? print("主進(jìn)程執(zhí)行完成了啦")

? ? # 讓子進(jìn)程直接銷(xiāo)毀,表示終止執(zhí)行, 主進(jìn)程退出之前,把所有的子進(jìn)程直接銷(xiāo)毀就可以了

? ? work_process.terminate()

? ? # 總結(jié): 主進(jìn)程會(huì)等待所有的子進(jìn)程執(zhí)行完成以后程序再退出

小結(jié):

? 進(jìn)程之間不共享全局變量

? 主進(jìn)程會(huì)等待所有的子進(jìn)程執(zhí)行完成程序再退出

4.進(jìn)程間通信-Queue

<1>Queue的使用

可以使用multiprocessing模塊的Queue實(shí)現(xiàn)多進(jìn)程之間的數(shù)據(jù)傳遞,Queue本身是一個(gè)消息隊(duì)列程序

首先用一個(gè)小實(shí)例來(lái)演示一下Queue的工作原理:

import multiprocessing

import time

if __name__ == '__main__':

? ? # 創(chuàng)建消息隊(duì)列, 3:表示隊(duì)列中最大消息個(gè)數(shù)

? ? queue = multiprocessing.Queue(3)

? ? # 放入數(shù)據(jù)

? ? queue.put(1)

? ? queue.put("hello")

? ? queue.put([3,5])

? ? # 總結(jié): 隊(duì)列可以放入任意數(shù)據(jù)類(lèi)型

? ? # 提示: 如果隊(duì)列滿了,需要等待隊(duì)列有空閑位置才能放入數(shù)據(jù),否則一直等待

? ? # queue.put((5,6))

? ? # 提示: 如果隊(duì)列滿了,不等待隊(duì)列有空閑位置,如果放入不成功直接崩潰

? ? # queue.put_nowait((5,6))

? ? # 建議: 向隊(duì)列放入數(shù)據(jù)統(tǒng)一使用put

? ? # 查看隊(duì)列是否滿了

? ? # print(queue.full())

? ? # 注意點(diǎn):queue.empty()判斷隊(duì)列是否空了不可靠

? ? # 查看隊(duì)列是否空了

? ? # print(queue.empty())

? ? # 解決辦法: 1. 加延時(shí)操作 2. 使用判斷隊(duì)列的個(gè)數(shù),不使用empty

? ? # time.sleep(0.01)

? ? if queue.qsize() == 0:

? ? ? ? print("隊(duì)列為空")

? ? else:

? ? ? ? print("隊(duì)列不為空")

? ? # 獲取隊(duì)列的個(gè)數(shù)

? ? size = queue.qsize()

? ? print(size)

? ? # 獲取數(shù)據(jù)

? ? value = queue.get()

? ? print(value)

? ? # 獲取隊(duì)列的個(gè)數(shù)

? ? size = queue.qsize()

? ? print(size)

? ? # 獲取數(shù)據(jù)

? ? value = queue.get()

? ? print(value)

? ? # 獲取數(shù)據(jù)

? ? value = queue.get()

? ? print(value)

? ? # 獲取隊(duì)列的個(gè)數(shù)

? ? size = queue.qsize()

? ? print(size)

? ? # 提示:如果隊(duì)列空了,再取值需要等待,只有隊(duì)列有值以后才能獲取隊(duì)列中數(shù)據(jù)

? ? # value = queue.get()

? ? # print(value)

? ? # queue.get_nowait()提示: 如果隊(duì)列空了 ,不需要等待隊(duì)列有值,但是如果取值的時(shí)候發(fā)現(xiàn)隊(duì)列空了直接崩潰

? ? # 建議大家: 向隊(duì)列取值使用get

? ? # value = queue.get_nowait()

? ? # print(value)

說(shuō)明:

初始化Queue()對(duì)象時(shí)(例如:q=Queue()),若括號(hào)中沒(méi)有指定最大可接收的消息數(shù)量,或數(shù)量為負(fù)值,那么就代表可接受的消息數(shù)量沒(méi)有上限(直到內(nèi)存的盡頭);

? Queue.qsize():返回當(dāng)前隊(duì)列包含的消息數(shù)量;

? Queue.empty():如果隊(duì)列為空,返回True,反之False , 注意這個(gè)操作是不可靠的。

? Queue.full():如果隊(duì)列滿了,返回True,反之False;

? Queue.get([block[, timeout]]):獲取隊(duì)列中的一條消息,然后將其從列隊(duì)中移除,block默認(rèn)值為T(mén)rue;

1)如果block(阻塞)使用默認(rèn)值,且沒(méi)有設(shè)置timeout(暫時(shí)休息)(單位秒),消息列隊(duì)如果為空,此時(shí)程序?qū)⒈蛔枞ㄍT谧x取狀態(tài)),直到從消息列隊(duì)讀到消息為止,如果設(shè)置了timeout,則會(huì)等待timeout秒,若還沒(méi)讀取到任何消息,則拋出"Queue.Empty"異常;

2)如果block值為False,消息列隊(duì)如果為空,則會(huì)立刻拋出"Queue.Empty"異常;

? Queue.get_nowait():相當(dāng)Queue.get(False);

? Queue.put(item,[block[, timeout]]):將item消息寫(xiě)入隊(duì)列,block默認(rèn)值為T(mén)rue;

1)如果block使用默認(rèn)值,且沒(méi)有設(shè)置timeout(單位秒),消息列隊(duì)如果已經(jīng)沒(méi)有空間可寫(xiě)入,此時(shí)程序?qū)⒈蛔枞ㄍT趯?xiě)入狀態(tài)),直到從消息列隊(duì)騰出空間為止,如果設(shè)置了timeout,則會(huì)等待timeout秒,若還沒(méi)空間,則拋出"Queue.Full"異常;

2)如果block值為False,消息列隊(duì)如果沒(méi)有空間可寫(xiě)入,則會(huì)立刻拋出"Queue.Full"異常;

? Queue.put_nowait(item):相當(dāng)Queue.put(item, False);

<2>消息隊(duì)列Queue完成進(jìn)程間通信的演練

我們以Queue為例,在父進(jìn)程中創(chuàng)建兩個(gè)子進(jìn)程,一個(gè)往Queue里寫(xiě)數(shù)據(jù),一個(gè)從Queue里讀數(shù)據(jù):

import multiprocessing

import time

# 寫(xiě)入數(shù)據(jù)

def write_data(queue):

? ? for i in range(10):

? ? ? ? if queue.full():

? ? ? ? ? ? print("隊(duì)列滿了")

? ? ? ? ? ? break

? ? ? ? queue.put(i)

? ? ? ? time.sleep(0.2)

? ? ? ? print(i)

# 讀取數(shù)據(jù)

def read_data(queue):

? ? while True:

? ? ? ? # 加入數(shù)據(jù)從隊(duì)列取完了,那么跳出循環(huán)

? ? ? ? if queue.qsize() == 0:

? ? ? ? ? ? print("隊(duì)列空了")

? ? ? ? ? ? break

? ? ? ? value = queue.get()

? ? ? ? print(value)

if __name__ == '__main__':

? ? # 創(chuàng)建消息隊(duì)列

? ? queue = multiprocessing.Queue(5)

? ? # 創(chuàng)建寫(xiě)入數(shù)據(jù)的進(jìn)程

? ? write_process = multiprocessing.Process(target=write_data, args=(queue,))

? ? # 創(chuàng)建讀取數(shù)據(jù)的進(jìn)程

? ? read_process = multiprocessing.Process(target=read_data, args=(queue,))

? ? # 啟動(dòng)進(jìn)程

? ? write_process.start()

? ? # 主進(jìn)程等待寫(xiě)入進(jìn)程執(zhí)行完成以后代碼再繼續(xù)往下執(zhí)行

? ? write_process.join()

? ? read_process.start()

小結(jié):

? 從隊(duì)列取值使用get方法,向隊(duì)列放入值使用put方法

? 消息隊(duì)列判斷隊(duì)列是否為空不可靠,可以使用延時(shí)和根據(jù)個(gè)數(shù)進(jìn)行判斷

5.進(jìn)程池Pool

進(jìn)程池的好處:

? 根據(jù)任務(wù)自動(dòng)創(chuàng)建進(jìn)程

? 合理利用指定進(jìn)程完成多任務(wù)

<1>進(jìn)程池的概念

池子里面放的是進(jìn)程,進(jìn)程池會(huì)根據(jù)任務(wù)執(zhí)行情況自動(dòng)創(chuàng)建進(jìn)程,而且盡量少創(chuàng)建進(jìn)程,合理利用進(jìn)程池中的進(jìn)程完成多任務(wù)

(根據(jù)任務(wù)執(zhí)行情況自動(dòng)創(chuàng)建進(jìn)程,并不是一開(kāi)始就創(chuàng)建最大數(shù)量的進(jìn)程)

當(dāng)需要?jiǎng)?chuàng)建的子進(jìn)程數(shù)量不多時(shí),可以直接利用multiprocessing中的Process動(dòng)態(tài)成生多個(gè)進(jìn)程,但如果是上百甚至上千個(gè)目標(biāo),手動(dòng)的去創(chuàng)建進(jìn)程的工作量巨大,此時(shí)就可以用到multiprocessing模塊提供的Pool方法。

初始化Pool時(shí),可以指定一個(gè)最大進(jìn)程數(shù),當(dāng)有新的請(qǐng)求提交到Pool中時(shí),如果池還沒(méi)有滿,那么就會(huì)創(chuàng)建一個(gè)新的進(jìn)程用來(lái)執(zhí)行該請(qǐng)求;但如果池中的進(jìn)程數(shù)已經(jīng)達(dá)到指定的最大值,那么該請(qǐng)求就會(huì)等待,直到池中有進(jìn)程結(jié)束,才會(huì)用之前的進(jìn)程來(lái)執(zhí)行新的任務(wù).

<2>進(jìn)程池同步執(zhí)行任務(wù)

進(jìn)程池同步執(zhí)行任務(wù)表示進(jìn)程池中的進(jìn)程在執(zhí)行任務(wù)的時(shí)候一個(gè)執(zhí)行完成另外一個(gè)才能執(zhí)行,如果沒(méi)有執(zhí)行完會(huì)等待上一個(gè)進(jìn)程執(zhí)行

進(jìn)程池同步實(shí)例代碼

import multiprocessing

import time

# 拷貝任務(wù)

def work():

? ? print("復(fù)制中...", multiprocessing.current_process().pid)

? ? time.sleep(0.5)

if __name__ == '__main__':

? ? # 創(chuàng)建進(jìn)程池

? ? # 3:進(jìn)程池中進(jìn)程的最大個(gè)數(shù),如果不設(shè)置,默認(rèn)最大進(jìn)程個(gè)數(shù)為電腦CPU的核數(shù)

? ? pool = multiprocessing.Pool(3)

? ? # 模擬大批量的任務(wù),讓進(jìn)程池去執(zhí)行

? ? for i in range(5):

? ? ? ? # 循環(huán)讓進(jìn)程池執(zhí)行對(duì)應(yīng)的work任務(wù)

? ? ? ? # 同步執(zhí)行任務(wù),一個(gè)任務(wù)執(zhí)行完成以后另外一個(gè)任務(wù)才能執(zhí)行

? ? ? ? pool.apply(work)

<3>進(jìn)程池異步執(zhí)行任務(wù)

進(jìn)程池異步執(zhí)行任務(wù)表示進(jìn)程池中的進(jìn)程同時(shí)執(zhí)行任務(wù),進(jìn)程之間不會(huì)等待

異步執(zhí)行,任務(wù)執(zhí)行不會(huì)等待,多個(gè)任務(wù)一起執(zhí)行

進(jìn)程池名.apply_async(任務(wù)名)

? ? # 關(guān)閉進(jìn)程池,意思告訴主進(jìn)程以后不會(huì)有新的任務(wù)添加進(jìn)來(lái)

? ? 進(jìn)程池名.close()

? ? # 主進(jìn)程等待進(jìn)程池執(zhí)行完成以后程序再退出

? ? 進(jìn)程池名.join()

進(jìn)程池異步實(shí)例代碼

# 進(jìn)程池:池子里面放的進(jìn)程,進(jìn)程池會(huì)根據(jù)任務(wù)執(zhí)行情況自動(dòng)創(chuàng)建進(jìn)程,而且盡量少創(chuàng)建進(jìn)程,合理利用進(jìn)程池中的進(jìn)程完成多任務(wù)

import multiprocessing

import time

# 拷貝任務(wù)

def work():

? ? print("復(fù)制中...", multiprocessing.current_process().pid)

? ? # 獲取當(dāng)前進(jìn)程的守護(hù)狀態(tài)

? ? # 提示:使用進(jìn)程池創(chuàng)建的進(jìn)程是守護(hù)主進(jìn)程的狀態(tài)true,默認(rèn)自己通過(guò)Process創(chuàng)建的進(jìn)程不是守護(hù)主進(jìn)程的狀態(tài)false

? ? # print(multiprocessing.current_process().daemon)

? ? time.sleep(0.5)

if __name__ == '__main__':

? ? # 創(chuàng)建進(jìn)程池

? ? # 3:進(jìn)程池中進(jìn)程的最大個(gè)數(shù)

? ? pool = multiprocessing.Pool(3)

? ? # 模擬大批量的任務(wù),讓進(jìn)程池去執(zhí)行

? ? for i in range(5):

? ? ? ? # 循環(huán)讓進(jìn)程池執(zhí)行對(duì)應(yīng)的work任務(wù)

? ? ? ? # 同步執(zhí)行任務(wù),一個(gè)任務(wù)執(zhí)行完成以后另外一個(gè)任務(wù)才能執(zhí)行

? ? ? ? # pool.apply(work)

? ? ? ? # 異步執(zhí)行,任務(wù)執(zhí)行不會(huì)等待,多個(gè)任務(wù)一起執(zhí)行

? ? ? ? pool.apply_async(work)

? ? # 關(guān)閉進(jìn)程池,意思告訴主進(jìn)程以后不會(huì)有新的任務(wù)添加進(jìn)來(lái)

? ? pool.close()

? ? # 主進(jìn)程等待進(jìn)程池執(zhí)行完成以后程序再退出

? ? pool.join()

小結(jié):

multiprocessing.Pool常用函數(shù)解析:

? 同步執(zhí)行:apply(func[, args[, kwds]]): 阻塞方式調(diào)用函數(shù),args表示以元組方式給函數(shù)傳參,kwds表示以字典方式給函數(shù)傳參

? 異步執(zhí)行:apply_async(func[, args[, kwds]]) :使用非阻塞方式調(diào)用函數(shù),args表示以元組方式給函數(shù)傳參,kwds表示以字典方式給函數(shù)傳參

? close():關(guān)閉Pool,使其不再接受新的任務(wù);

? terminate():不管任務(wù)是否完成,立即終止;

? join():主進(jìn)程阻塞,等待子進(jìn)程的退出, 必須在close或terminate之后使用;

6.進(jìn)程、線程對(duì)比

<1>功能對(duì)比

? 進(jìn)程,能夠完成多任務(wù),比如 在一臺(tái)電腦上能夠同時(shí)運(yùn)行多個(gè)QQ

? 線程,能夠完成多任務(wù),比如 一個(gè)QQ中的多個(gè)聊天窗口

<2>定義對(duì)比

? 進(jìn)程是系統(tǒng)進(jìn)行資源分配基本單位,每啟動(dòng)一個(gè)進(jìn)程操作系統(tǒng)都需要為其分配運(yùn)行資源。

? 線程是CPU調(diào)度基本單位,是運(yùn)行程序中的一個(gè)執(zhí)行分支。

? 總結(jié):進(jìn)程是操作系統(tǒng)資源分配的基本單位,線程是CPU調(diào)度的基本單位

<3>關(guān)系對(duì)比

? 線程是依附在進(jìn)程里面的,沒(méi)有進(jìn)程就沒(méi)有線程

? 一個(gè)進(jìn)程默認(rèn)提供一條線程,進(jìn)程可以創(chuàng)建多個(gè)線程

<4>區(qū)別

? 進(jìn)程之間不共享全局變量

? 線程之間共享全局變量,但是要注意資源競(jìng)爭(zhēng)的問(wèn)題,解決辦法: 互斥鎖或者線程同步

? 創(chuàng)建進(jìn)程的資源開(kāi)銷(xiāo)要比創(chuàng)建線程的資源開(kāi)銷(xiāo)要大

? 進(jìn)程是操作系統(tǒng)資源分配的基本單位,線程是CPU調(diào)度的基本單位

? 線程不能夠獨(dú)立執(zhí)行,必須依存在進(jìn)程中

? 多進(jìn)程開(kāi)發(fā)比單進(jìn)程多線程開(kāi)發(fā)穩(wěn)定性要強(qiáng)

<5>優(yōu)缺點(diǎn)

多進(jìn)程:

? 優(yōu)點(diǎn):可以用多核

? 缺點(diǎn):資源開(kāi)銷(xiāo)大

多線程:

? 優(yōu)點(diǎn):資源開(kāi)銷(xiāo)小

? 缺點(diǎn):不能使用多核

7.文件夾拷貝器-多任務(wù)

<1>功能要求

? 使用進(jìn)程池完成多任務(wù)文件夾的拷貝

import os

import shutil

import multiprocessing

# import time

# 文件拷貝任務(wù)

def copy_work(src_dir, dst_dir, file_name):

? ? # 查看進(jìn)程對(duì)象

? ? pid = multiprocessing.current_process().pid

? ? print(pid)

? ? # 拼接源文件的路徑

? ? src_file_path = src_dir + "/" + file_name

? ? # 拼接目標(biāo)文件的路徑

? ? dst_file_path = dst_dir + "/" + file_name

? ? with open(dst_file_path, "wb") as dst_file:

? ? ? ? # 打源文件讀取文件中的數(shù)據(jù)

? ? ? ? with open(src_file_path, "rb") as src_file:

? ? ? ? ? ? while True:

? ? ? ? ? ? ? ? # 讀取數(shù)據(jù)

? ? ? ? ? ? ? ? src_file_data = src_file.read(1024)

? ? ? ? ? ? ? ? if src_file_data:

? ? ? ? ? ? ? ? ? ? # 寫(xiě)入到目標(biāo)文件里面

? ? ? ? ? ? ? ? ? ? dst_file.write(src_file_data)

? ? ? ? ? ? ? ? else:

? ? ? ? ? ? ? ? ? ? break

? ? # time.sleep(0.5)

if __name__ == '__main__':

? ? # 源目錄

? ? src_dir = "test"

? ? # 目標(biāo)目錄

? ? dst_dir = "/home/python/Desktop/test"

? ? # 判斷文件夾是否存在

? ? if os.path.exists(dst_dir):

? ? ? ? # 存在則刪除文件夾及文件夾里面的所有文件

? ? ? ? shutil.rmtree(dst_dir)

? ? # 創(chuàng)建目標(biāo)文件夾

? ? os.mkdir(dst_dir)

? ? # 獲取源目錄里面文件的列表

? ? file_name_list = os.listdir(src_dir)

? ? # 創(chuàng)建進(jìn)程池

? ? pool = multiprocessing.Pool(3)

? ? # 遍歷文件里面獲取文件名

? ? for file_name in file_name_list:

? ? ? ? # 使用進(jìn)程池執(zhí)行拷貝任務(wù),使用*args和**kwagrs傳參數(shù)!此處選擇元組

? ? ? ? pool.apply_async(copy_work, (src_dir, dst_dir, file_name))

? ? # 關(guān)閉進(jìn)程池

? ? pool.close()

? ? # 主進(jìn)程等待進(jìn)程池執(zhí)行完成以后程序再退出

? ? pool.join()

小結(jié):

進(jìn)程池在執(zhí)行任務(wù)的時(shí)候會(huì)盡量少創(chuàng)建進(jìn)程,合理利用現(xiàn)有進(jìn)程完成多任務(wù),這樣可以減少資源開(kāi)銷(xiāo)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 進(jìn)程間通信——隊(duì)列和管道(multiprocess.Queue、multiprocess.Pipe) 進(jìn)程間通信 ...
    go以恒閱讀 1,794評(píng)論 0 3
  • 寫(xiě)在前面的話 代碼中的# > 表示的是輸出結(jié)果 輸入 使用input()函數(shù) 用法 注意input函數(shù)輸出的均是字...
    FlyingLittlePG閱讀 2,801評(píng)論 0 8
  • 1.進(jìn)程 1.1多線程的引入 現(xiàn)實(shí)生活中 有很多的場(chǎng)景中的事情是同時(shí)進(jìn)行的,比如開(kāi)車(chē)的時(shí)候手和腳共同來(lái)駕駛汽車(chē),再...
    TENG書(shū)閱讀 514評(píng)論 0 0
  • 靈魂是意識(shí)的聚集!人的意識(shí)是沒(méi)有發(fā)展的,散亂的,修煉就是讓意識(shí)聚焦在自己身上,無(wú)論外面呈現(xiàn)出來(lái)的是什么,都可以照見(jiàn)...
    竺子閱讀 158評(píng)論 0 0
  • 1. 作為一個(gè)沒(méi)能力在上海置業(yè)的外來(lái)人口,搬家是每隔幾年或每隔一段時(shí)間都要面臨的事情。 盡管很多時(shí)候都是被動(dòng)的。 ...
    嫻雅居士閱讀 257評(píng)論 2 2