day32:進程

目錄

1.進程的基本概念

2.進程初體驗

3.join:先子後主

4.守護進程:deamon

5.兩張和進程相關的圖

進程的基本概念

什麼是進程?

進程就是正在運行的程式,它是作業系統中,資源分配的最小單位

什麼是資源分配?

資源分配:分配的是cpu和記憶體等物理資源

Linux中幾個關於進程的指令

ps -aux    查看進程號

ps -aux | grep 2860   查看對應進程號的進程

kill -9 2860   殺死進程

pid和ppid

獲取當前進程id: os.getpid()

獲取當前進程的父進程id: os.getppid()

進程初體驗

1.進程的基本使用

在使用進程之前,需要調用Process: from multiprocessing import Process

# (1) 進程的基本使用
def func():
    print("1.子進程id>>{},2父進程id>>{}".format(os.getpid(),os.getppid()))

# 為了解決windows 和 linux 系統的兼容問題,下面這句話必須加上,否則報錯
if __name__ == "__main__":
    # 創建子進程,返回進程對象,執行func這個任務
    p = Process(target=func)
    # 調用子進程
    p.start()

2.創建帶有參數的進程

def func(n):
    for i in range(1,n+1):
        print("1.子進程id>>{},2父進程id>>{}".format(os.getpid(),os.getppid()))

if __name__ == "__main__":
    n = 5
    #創建子進程
    p = Process(target=func,args=(n,))
    #調用子進程
    p.start()

    for i in range(1,n+1):
        print("*" * i)

執行結果如下圖所示

產生如上結果的原因:因為子進程分配資源需要時間,而主進程早已經分配好資源了,不需要這個時間。所以主進程的內容先列印,子進程的內容後列印

3.進程之間的數據彼此隔離

count = 10
def func():
    global count
    count += 1
    print("我是子進程count={}".format(count))

if __name__ == "__main__":
    p=Process(target=func)
    p.start()
    time.sleep(1)
    print(count)

執行結果如下圖所示

產生如上結果的原因:如下圖所示,黃色部分都是子進程中的內容,子進程中有+1操作,所以子進程中的count肯定為11

但是主進程並沒有任何操作,只是單純的列印了一下count,所以主進程中的count為10

 4.多個進程之間是非同步並發

關於主進程和子進程,你需要注意的點:

1.多個進程之間是非同步並發的程式,因為cpu的調度策略問題,不一定哪個任務先執行,哪個任務後執行.

整體而言,主進程比子進程創建的速度要快,cpu遇到阻塞會立刻切換任務,等到阻塞態的任務變成了就緒態,cpu再回來執行

2.主程式會默認等到所有的子程式執行結束之後,在統一關閉程式,釋放資源.

若不等待,有可能在後台存有多個未執行結束的子進程,會變成殭屍進程,不停的佔用cpu,記憶體

增加系統的壓力,所有方便於對進程的管理,主進程默認等待子進程.

def func(n):
    time.sleep(random.randrange(3))
    print("數字{}<=>1.子進程id>>{},2父進程id>>{}".format(n,os.getpid(),os.getppid()))

if __name__ == "__main__":
    for i in range(1,11):
        Process(target=func,args=(i,)).start()
        
    print("主進程執行結束了....")
    print(os.getpid())

執行結果如下圖所示

join:先子後主

1.join基本語法

def func():
    print("發送第一封郵箱,要求漲工資")


if __name__ == "__main__":
    p = Process(target=func)
    p.start()

    # 必須等待子進程全部執行結束之後,在執行主進程中的程式碼,用join來同步子父進程.
    p.join()
    # time.sleep(1)
    print("發送第二封郵箱,漲到一個月6萬")

執行結果如下圖所示

2.join:多個子進程

def func(i):
    time.sleep(1)
    print("發送第%s封郵箱,要求升職加薪" % (i))


if __name__ == "__main__":
    lst = []
    for i in range(10):
        p = Process(target=func, args=(i,))
        p.start()
        lst.append(p) # 把創建的十個子進程對象方放到列表中,現在他們處於就緒態

    for i in lst:
        i.join() # 十個子進程對象同時join

    print("主進程發最後一封郵件:此致敬禮~")

執行結果如下圖所示

請注意!!!千萬不要寫成如下寫法:

守護進程deamon

1.守護進程的基本概念 

概念:

守護進程守護的是主進程,如果主進程中的所有程式碼執行完畢了,

當前這個守護進程會被立刻殺死,立刻終止.

語法:

進程.daemon = True—->設置當前這個進程為守護進程

必須寫在start()調用進程之前進行設置

2.守護進程的基本使用方法

def func():
    print("start當前子進程")
    time.sleep(1)
    print("end當前子進程")


if __name__ == "__main__":
    p = Process(target=func)
    p.daemon = True
    p.start()

    print("主進程執行結束 ... ")

執行結果如下圖所示

3.守護進程:多個子進程

def func1():
    count = 1
    while True:
        print("*" * count)
        time.sleep(0.5)
        count += 1


def func2():
    print("start func2 當前子進程任務")
    time.sleep(3)
    print("end   func2 當前子進程任務")


if __name__ == "__main__":
    p1 = Process(target=func1)
    p2 = Process(target=func2)

    # 設置p1這個進程對象為守護進程
    p1.daemon = True

    p1.start()
    p2.start()

    time.sleep(1)

    print("主進程執行結束 ... ")

執行結果如下圖所示

4.守護進程實際用途:監控報活

# 守護進行
def alive():
    while True:
        print("給監控的總伺服器發消息,報告自己的存活狀態, i am alive~")
        time.sleep(1)


# 執行任務
def func():
    while True:
        try:
            time.sleep(1)
            raise RuntimeError
            print("當前5號伺服器功能:對日誌進行數據分析.... ")
        except:
            break
        # pass


if __name__ == "__main__":
    # 創建2個子進程
    p1 = Process(target=alive)
    p2 = Process(target=func)
    # 設置p1為守護進程
    p1.daemon = True

    p1.start()
    p2.start()

    # 必須等到p2任務執行結束之後,在向下執行.
    p2.join()

    print("當前伺服器狀態異常 ... ")

在一切都很正常的時候,它的運行結果是這樣的

 

當出現問題時,它的運行結果是這樣的

 

兩張和進程相關的圖