1. 程式人生 > >python通過多進程實行多任務

python通過多進程實行多任務

-s hung name 哪裏 簡單 共享 不相信 time 多任務

#原創,轉載請聯系

在開始之前,我們要知道什麽是進程。道理很簡單,你平時電腦打開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兩個被創建的子進程外。當然還有主進程。主進程就是我們從頭到尾的代碼,包括子進程也是由主進程創建的。

註意的點有:

1.首先解釋一下並發:並發就是當任務數大於cpu核數時,通過操作系統的各種任務調度算法,實現多個任務“一起”執行。(實際上總有一些任務不在執行,因為切換任務相當快,看上去想同時執行而已。)

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

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

4.主進程默認創建的是非守護進程。註意,結合3.和5.看。

5.但是!但是!如果子進程是守護進程的話,那麽主進程運行完最後一句代碼後,主進程會直接關閉,不管你子進程運行完了沒有!

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

不相信?

那我們來測試下

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‘]

一針見血了吧,哈哈~

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

python通過多進程實行多任務