python多任務-進程

程序是以二進制形式存放在硬盤之上的,當啟動程序?qū)?shù)據(jù)(代碼)加載至內(nèi)存中就稱之為進程砸西。
進程是一組資源(包括:代碼,顯示器址儒,硬盤芹枷,網(wǎng)絡(luò)....)的統(tǒng)稱。線程也能實現(xiàn)多任務莲趣,但相對進程來說是輕量級的鸳慈。
實際上進程是一個資源分配的單位,實際上操縱數(shù)據(jù)的是線程喧伞,一個進程至少一個主線程走芋。代碼至上而下運行的時候?qū)嶋H上就是主線程在運行绩郎,當遇到一個Thread對象調(diào)用start方法時,就再開一個線程翁逞。當遇到一個Process對象調(diào)用start方法時就將當前進程的資源復制一份到內(nèi)存的一個區(qū)域中肋杖,以一個新的進程去運行,它擁有獨立的內(nèi)存單元挖函,這就叫子進程状植。子進程因為有自己的資源,所以不與父進程共享全局變量怨喘。
簡單的來說進程是資源分配的單位津畸,而線程是操作系統(tǒng)調(diào)度的單位。

# -*- coding:utf-8 -*-
from multiprocessing import Process
import os
import time

nums = [11, 22]

def work1():
    """子進程要執(zhí)行的代碼"""
    print("in process1 pid=%d ,nums=%s" % (os.getpid(), nums))
    for i in range(3):
        nums.append(i)
        time.sleep(1)
        print("in process1 pid=%d ,nums=%s" % (os.getpid(), nums))

def work2():
    """子進程要執(zhí)行的代碼"""
    print("in process2 pid=%d ,nums=%s" % (os.getpid(), nums))

if __name__ == '__main__':
    p1 = Process(target=work1)
    p1.start()
    p1.join()

    p2 = Process(target=work2)
    p2.start()

結(jié)果:

in process1 pid=7956 ,nums=[11, 22]
in process1 pid=7956 ,nums=[11, 22, 0]
in process1 pid=7956 ,nums=[11, 22, 0, 1]
in process1 pid=7956 ,nums=[11, 22, 0, 1, 2]
in process2 pid=22332 ,nums=[11, 22]

Process語法結(jié)構(gòu)如下:

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

target:如果傳遞了函數(shù)的引用必怜,可以任務這個子進程就執(zhí)行這里的代碼
args:給target指定的函數(shù)傳遞的參數(shù)肉拓,以元組的方式傳遞
kwargs:給target指定的函數(shù)傳遞命名參數(shù)
name:給進程設(shè)定一個名字,可以不設(shè)定
group:指定進程組梳庆,大多數(shù)情況下用不到
Process創(chuàng)建的實例對象的常用方法:

start():啟動子進程實例(創(chuàng)建子進程)
is_alive():判斷進程子進程是否還在活著
join([timeout]):是否等待子進程執(zhí)行結(jié)束暖途,或等待多少秒
terminate():不管任務是否完成,立即終止子進程
Process創(chuàng)建的實例對象的常用屬性:

name:當前進程的別名膏执,默認為Process-N丧肴,N為從1開始遞增的整數(shù)
pid:當前進程的pid(進程號)

既然進程間數(shù)據(jù)不共享那么進程間又是怎么通信的呢
操作系統(tǒng)提供了很多機制實現(xiàn)進程間通信,可以使用文件胧后,socket,以及內(nèi)存抱环。在內(nèi)存中劃分一塊區(qū)域壳快,一個進程寫另一個進程讀就可以完成進程間通信了。

Queue的使用

可以使用multiprocessing模塊的Queue實現(xiàn)多進程之間的數(shù)據(jù)傳遞镇草,Queue本身是一個消息列隊程序眶痰。

from multiprocessing import Process, Queue
import os, time, random

# 寫數(shù)據(jù)進程執(zhí)行的代碼:
def write(q):
    for value in ['A', 'B', 'C']:
        print('Put %s to queue...' % value)
        q.put(value)
        time.sleep(random.random())

# 讀數(shù)據(jù)進程執(zhí)行的代碼:
def read(q):
    while True:
        if not q.empty():
            value = q.get(True)
            print('Get %s from queue.' % value)
            time.sleep(random.random())
        else:
            break

if __name__=='__main__':
    # 父進程創(chuàng)建Queue,并傳給各個子進程:
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 啟動子進程pw梯啤,寫入:
    pw.start()    
    # 等待pw結(jié)束:
    pw.join()
    # 啟動子進程pr竖伯,讀取:
    pr.start()
    pr.join()
    # pr進程里是死循環(huán),無法等待其結(jié)束因宇,只能強行終止:
    print('')
    print('所有數(shù)據(jù)都寫入并且讀完')

結(jié)果:

Put A to queue...
Put B to queue...
Put C to queue...
Get A from queue.
Get B from queue.
Get C from queue.

所有數(shù)據(jù)都寫入并且讀完

進程池

當需要創(chuàng)建的子進程數(shù)量不多時七婴,可以直接利用multiprocessing中的Process動態(tài)成生多個進程,但如果是上百甚至上千個目標察滑,手動的去創(chuàng)建進程的工作量巨大打厘,此時就可以用到multiprocessing模塊提供的Pool方法。

初始化Pool時贺辰,可以指定一個最大進程數(shù)户盯,當有新的請求提交到Pool中時嵌施,如果池還沒有滿,那么就會創(chuàng)建一個新的進程用來執(zhí)行該請求莽鸭;但如果池中的進程數(shù)已經(jīng)達到指定的最大值吗伤,那么該請求就會等待,直到池中有進程結(jié)束硫眨,才會用之前的進程來執(zhí)行新的任務
任務數(shù)固定用Process創(chuàng)建子進程足淆,不固定則用Pool來創(chuàng)建進程池

通過進程池(Pool)創(chuàng)建的子進程,主進程并不會等子進程執(zhí)行完才退出捺球,這時候就需要調(diào)用po.join堵塞主進程直到子進程執(zhí)行完畢缸浦。

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

apply_async(func[, args[, kwds]]) :使用非阻塞方式調(diào)用func(并行執(zhí)行,堵塞方式必須等待上一個進程退出才能執(zhí)行下一個進程),args為傳遞給func的參數(shù)列表袄简,kwds為傳遞給func的關(guān)鍵字參數(shù)列表霜威;
close():關(guān)閉Pool,使其不再接受新的任務卜高;
terminate():不管任務是否完成,立即終止南片;
join():主進程阻塞掺涛,等待子進程的退出, 必須在close或terminate之后使用疼进;

子進程如果發(fā)生異常并不會產(chǎn)生異常信息
注意:進程池之間想要通信不能使用multiprocessing模塊的Queue薪缆,而是使用multiprocessing.Manager()中的Queue(),否則會得到一條如下的錯誤信息:

RuntimeError: Queue objects should only be shared between processes through inheritance.

示例:

# -*- coding:utf-8 -*-

# 修改import中的Queue為Manager
from multiprocessing import Manager,Pool
import os,time,random

def reader(q):
    print("reader啟動(%s),父進程為(%s)" % (os.getpid(), os.getppid()))
    for i in range(q.qsize()):
        print("reader從Queue獲取到消息:%s" % q.get(True))

def writer(q):
    print("writer啟動(%s),父進程為(%s)" % (os.getpid(), os.getppid()))
    for i in "itcast":
        q.put(i)

if __name__=="__main__":
    print("(%s) start" % os.getpid())
    q = Manager().Queue()  # 使用Manager中的Queue
    po = Pool()
    po.apply_async(writer, (q,))

    time.sleep(1)  # 先讓上面的任務向Queue存入數(shù)據(jù)伞广,然后再讓下面的任務開始從中取數(shù)據(jù)

    po.apply_async(reader, (q,))
    po.close()
    po.join()
    print("(%s) End" % os.getpid())

結(jié)果:

(21424) start
writer啟動(25556),父進程為(21424)
reader啟動(9808),父進程為(21424)
reader從Queue獲取到消息:i
reader從Queue獲取到消息:t
reader從Queue獲取到消息:c
reader從Queue獲取到消息:a
reader從Queue獲取到消息:s
reader從Queue獲取到消息:t
(21424) End
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拣帽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嚼锄,更是在濱河造成了極大的恐慌减拭,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件区丑,死亡現(xiàn)場離奇詭異拧粪,居然都是意外死亡,警方通過查閱死者的電腦和手機沧侥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門可霎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人宴杀,你說我怎么就攤上這事啥纸。” “怎么了婴氮?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵斯棒,是天一觀的道長盾致。 經(jīng)常有香客問我,道長荣暮,這世上最難降的妖魔是什么庭惜? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮穗酥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘砾跃。我一直安慰自己骏啰,他們只是感情好,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布翘骂。 她就那樣靜靜地躺著草丧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪厂汗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天角寸,我揣著相機與錄音菩混,去河邊找鬼忿墅。 笑死,一個胖子當著我的面吹牛沮峡,可吹牛的內(nèi)容都是我干的疚脐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼邢疙,長吁一口氣:“原來是場噩夢啊……” “哼棍弄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起疟游,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤呼畸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后颁虐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蛮原,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年聪廉,在試婚紗的時候發(fā)現(xiàn)自己被綠了瞬痘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡板熊,死狀恐怖框全,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情干签,我是刑警寧澤津辩,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站容劳,受9級特大地震影響喘沿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜竭贩,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一蚜印、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧留量,春花似錦窄赋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至可岂,卻和暖如春错敢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缕粹。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工稚茅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纸淮,地道東北人。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓峰锁,卻偏偏與公主長得像萎馅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子虹蒋,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

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

  • 一糜芳、總體內(nèi)容 1.1、進程魄衅、程序的概念 1.2峭竣、使用 Process 完成多進程- multiprocessing...
    IIronMan閱讀 765評論 0 1
  • 進程、進程的使用晃虫、進程注意點皆撩、進程間通信-Queue、進程池Pool哲银、進程與線程對比扛吞、文件夾拷貝器-多任務 1.進...
    Cestine閱讀 819評論 0 0
  • 一. 操作系統(tǒng)概念 操作系統(tǒng)位于底層硬件與應用軟件之間的一層.工作方式: 向下管理硬件,向上提供接口.操作系統(tǒng)進行...
    月亮是我踢彎得閱讀 5,974評論 3 28
  • 必備的理論基礎(chǔ) 1.操作系統(tǒng)作用: 隱藏丑陋復雜的硬件接口,提供良好的抽象接口荆责。 管理調(diào)度進程滥比,并將多個進程對硬件...
    drfung閱讀 3,546評論 0 5
  • 線程 操作系統(tǒng)線程理論 線程概念的引入背景 進程 之前我們已經(jīng)了解了操作系統(tǒng)中進程的概念盲泛,程序并不能單獨運行,只有...
    go以恒閱讀 1,646評論 0 6