python經過多進程實行多任務

#原創,轉載請聯繫python

  

    在開始以前,咱們要知道什麼是進程。道理很簡單,你平時電腦打開QQ客戶端,就是一個進程。再打開一個QQ客戶端,又是一個進程。那麼,在python中如何用一篇代碼就能夠開啓幾個進程呢?經過一個簡單的例子來演示:算法

import multiprocessing
import time


def task1():
    while True:
        time.sleep(1)
        print("I am task1")

def task2():
    while True:
        time.sleep(2)
        print("I am task2")


if __name__ == '__main__':
    p1 = multiprocessing.Process(target=task1)  # multiprocessing.Process建立了子進程對象p1
    p2 = multiprocessing.Process(target=task2)  # multiprocessing.Process建立了子進程對象p2
    p1.start()  # 子進程p1啓動
    p2.start()  # 子進程p2啓動
    print("I am main task")  # 這是主進程的任務

輸出結果:
I am main task
I am task1
I am task2
I am task1
I am task1
I am task2
I am task1
I am task1
I am task2
...
...

    能夠看到子進程對象是由multiprocessing模塊中的Process類建立的。除了p1,p2兩個被建立的子進程外。固然還有主進程。主進程就是咱們從頭至尾的代碼,包括子進程也是由主進程建立的。併發

注意的點有:app

1.首先解釋一下併發:併發就是當任務數大於cpu核數時,經過操做系統的各類任務調度算法,實現多個任務「一塊兒」執行。(實際上總有一些任務不在執行,由於切換任務至關快,看上去想同時執行而已。)函數

2.當是併發的狀況下,子進程與主進程的運行都是沒有順序的,CPU會採用時間片輪尋的方式,哪一個程序先要運行就先運行哪一個。測試

3.主進程會默認等待全部子進程執行完畢後,它纔會退出。因此在上面的例子中,p1,p2子進程是死循環進程,主進程的最後一句代碼print("I am main task")雖然運行完了,可是主進程並不會關閉,他會一直等待着子進程。spa

4.主進程默認建立的是非守護進程。注意,結合3.和5.看。操作系統

5.可是!可是!若是子進程是守護進程的話,那麼主進程運行完最後一句代碼後,主進程會直接關閉,無論你子進程運行完了沒有!線程

 -------------------------------------------------------------------------------------------------------------我是一條分割線------------------------------------------------------------------------------------------------------------------------------------code

不相信?

那咱們來測試下

import multiprocessing
import time


def task1():
    while True:
        time.sleep(1)
        print("I am task1")

def task2():
    while True:
        time.sleep(2)
        print("I am task2")


if __name__ == '__main__':
    p1 = multiprocessing.Process(target=task1)
    p2 = multiprocessing.Process(target=task2)
    p1.daemon = True  # 設置p1子進程爲守護進程
    p2.daemon = True  # 設置p2子進程爲守護進程
    p1.start()
    p2.start()
    print("I am main task")

輸出結果:
I am main task

輸出結果是否是有點奇怪。爲何p1,p2子進程都沒有輸出的?

讓咱們來整理一下思路:

1.建立p1,p2子進程

2.設置p1,p2子進程爲守護進程

3.p1,p2子進程開啓

4.p1,p2子進程代碼裏面都有休眠時間,因此cpu爲了避免浪費時間,先作主進程後續的代碼。

5.執行主進程後續的代碼,print("I am main task")

6.主進程後續的代碼執行完成了,因此剩下的子進程是守護進程的,全都要關閉了。可是,若是主進程的代碼執行完了,有兩個子進程,一個是守護的,一個非守護的,怎麼辦呢?其實,他會等待非守護的那個子進程運行完,而後三個進程一塊兒關閉。

7.p1,p2還在休眠時間內就被終結生命了,因此什麼輸出都沒有。

裏面涉及到兩個知識點:

1.當主進程結束後,會發一個消息給子進程(守護進程),守護進程收到消息,則當即結束

2.CPU是按照時間片輪尋的方式來運行多進程的。哪一個合適的哪一個運行,若是你的子進程裏都有time.sleep。那我CPU爲了避免浪費資源,確定先去幹點其餘的事情啊。

那麼,守護進程隨時會被中斷,他的存在乎義在哪裏的?

其實,守護進程主要用來作與業務無關的任務,可有可無的任務,無關緊要的任務,好比內存垃圾回收,某些方法的執行時間的計時等。

-------------------------------------------------------------------------------------------------------------我是一條分割線------------------------------------------------------------------------------------------------------------------------------------

雖然知道怎麼簡單的建立子進程,可是若是要建立的子進程要傳入參數,應該怎麼操做呢?

import multiprocessing


def task(a,b,*args,**kwargs):
    print("a")
    print("b")
    print(args)
    print(kwargs)


if __name__ == '__main__':
    p1 = multiprocessing.Process(target=task,args=(1,2,3,4,5,6),kwargs={"name":"chichung","age":23})
    p1.start()
    print("主進程已經運行完最後一行代碼啦")

輸出:

主進程已經運行完最後一行代碼啦
a
b
(3, 4, 5, 6)
{'name': 'chichung', 'age': 23}

子進程要運行的函數須要傳入變量a,b,一個元組,一個字典。咱們建立子進程的時候,變量a,b要放進元組裏面,task函數取的時候會把前兩個取出來,分別賦值給a,b了。

-------------------------------------------------------------------------------------------------------------我是一條分割線------------------------------------------------------------------------------------------------------------------------------------

建立的子進程有幾個經常使用的方法:

p.start 開始執行子線程
p.name 查看子進程的名稱
p.pid 查看子進程的id
p.is_alive 判斷子進程是否存活
p.join(timeout)

阻塞主進程,當子進程p運行完畢後,再解開阻塞,讓主進程運行後續的代碼

若是timeout=2,就是阻塞主進程2s,這2s內主進程不能運行後續的代碼。過了2s後,就算子進程沒有運行完畢,主進程也能運行後續的代碼

p.terminate 終止子進程p的運行
import multiprocessing


def task(a,b,*args,**kwargs):
    print("a")
    print("b")
    print(args)
    print(kwargs)


if __name__ == '__main__':
    p1 = multiprocessing.Process(target=task,args=(1,2,3,4,5,6),kwargs={"name":"chichung","age":23})
    p1.start()
    print("p1子進程的名字:%s" % p1.name)
    print("p1子進程的id:%d" % p1.pid)
    p1.join()
    print(p1.is_alive())

輸出:
p1子進程的名字:Process-1
p1子進程的id:19345
a
b
(3, 4, 5, 6)
{'name': 'chichung', 'age': 23}
False

這個沒什麼好說的,本身體會一下......

-------------------------------------------------------------------------------------------------------------我是一條分割線------------------------------------------------------------------------------------------------------------------------------------

進程之間是不能夠共享全局變量的,即便子進程與主進程。道理很簡單,一個新的進程,其實就是佔用一個新的內存空間,不一樣的內存空間,裏面的變量確定不可以共享的。實驗證實以下:

import multiprocessing

g_list = [123]


def task1():
    g_list.append("task1")
    print(g_list)


def task2():
    g_list.append("task2")
    print(g_list)


def main_process():
    g_list.append("main_processs")
    print(g_list)


if __name__ == '__main__':
    p1 = multiprocessing.Process(target=task1)
    p2 = multiprocessing.Process(target=task2)
    p1.start()
    p2.start()
    main_process()

輸出:
[123, 'main_processs']
[123, 'task1']
[123, 'task2']

一針見血了吧,哈哈~

----------------------------------------------------------------------------------------------------------我是一條結束線,謝謝觀看~-----------------------------------------------------------------------------------------------------------------------

相關文章
相關標籤/搜索