首頁 >後端開發 >Python教學 >python多進程控制的教學講解(附範例)

python多進程控制的教學講解(附範例)

不言
不言轉載
2018-11-15 14:00:202003瀏覽

這篇文章帶給大家的內容是關於python多進程控制的教學講解(附範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

multiprocessing簡介

multiprocessing是python自帶的多進程模組,可以大批量的生成進程,在伺服器為多核心CPU時效果更好,類似於threading模組。相對於多線程,多進程由於獨享記憶體空間,更穩定安全,在運維裡面做些批量操作時,多進程有更多適用的場景

multiprocessing套件提供了本地和遠端兩種並發操作,有效的避開了使用子程序而不是全域解釋鎖定的線程,因此,multiprocessing可以有效利用到多核心處理

Process類別

在multiporcessing中,透過Process類別物件來批次產生進程,使用start()方法來啟動這個進程

1.語法

multiprocessing.Process(group=None,target=None,name=None,args=(),kwargs={},*)

group: 这个参数一般为空,它只是为了兼容threading.Tread
target: 这个参数就是通过run()可调用对象的方法,默认为空,表示没有方法被调用
name: 表示进程名
args: 传给target调用方法的tuple(元组)参数
kwargs: 传给target调用方法的dict(字典)参数

#2.Process類別的方法及物件

run()
該方法是進程的運作過程,可以在子類別中重寫此方法,一般也很少去重構

start()
#啟動進程,每個進程物件都必須被該方法呼叫

join([timeout])
等待進程終止,再往下執行,可以設定逾時時間

name
可以取得進程名稱,多個進程也可以是相同的名字

is_alive()
返回進程是否還存活,True or False,程式存活是指start()開始到子程序終止

daemon
守護程式的標記,一個布林值,在start()之後設定該值,表示是否後台運行
注意:如果設定了後台運行,那麼後台程式不運行再建立子程序

##pid##可以取得進程ID

exitcode子進程退出時的值,如果進程還沒有終止,值將會是None,如果是負值,表示子程序被終止

terminate()終止進程,如果是Windows,則使用terminateprocess(),該方法對已經退出和結束的進程,將不會執行

以下為一個簡單的例子:

#-*- coding:utf8 -*- 
import multiprocessing
import time

def work(x):
   time.sleep(1)
   print time.ctime(),'这是子进程[{0}]...'.format(x)

if __name__ == '__main__':
    for i in range(5):
        p = multiprocessing.Process(target=work,args=(i,))
        print '启动进程数:{0}'.format(i)
        p.start()
        p.deamon = True

python多進程控制的教學講解(附範例)當然也可以顯示每個行程的ID

#-*- coding:utf8 -*- 
import multiprocessing
import time
import os

def work(x):
   time.sleep(1)
   ppid = os.getppid()
   pid  = os.getpid()
   print time.ctime(),'这是子进程[{0},父进程:{1},子进程:{2}]...'.format(x,ppid,pid)

if __name__ == '__main__':
    for i in range(5):
        p = multiprocessing.Process(target=work,args=(i,))
        print '启动进程数:{0}'.format(i)
        p.start()
        p.deamon = True

python多進程控制的教學講解(附範例)但在實際使用的過程中,並不只是並發完就可以了,比如,有30個任務,由於伺服器資源有限,每次並發5個任務,這裡還涉及到30個任務怎麼獲取的問題,另外並發的進程任務執行時間很難保證一致,尤其是需要時間的任務,可能並發5個任務,有3個已經執行完了,2個還需要很長時間執行,總不能等到這兩個進程執行完了,再繼續執行後面的任務,因此進程控制就在此有了使用場景,可以利用Process的方法和一些multiprocessing的包,類等結合使用

進程控制及通訊常用類別

一、Queue類別

類似python自帶的Queue.Queue,主要用在比較小的佇列上面

語法:

multiprocessing.Queue([maxsize])

類別方法:

qsize()
傳回佇列的大致大小,因為多行程或多執行緒一直在消耗佇列,因此該資料不一定正確

empty()

判斷佇列是否為空,如果是,則傳回True,否則False

full()

判斷佇列是否已滿,如果是,則傳回True,否則False

put(obj[, block[, timeout]])

#將物件放入佇列,可選參數block為True,timeout為None

get()

從佇列取出物件

#-*- coding:utf8 -*-
from multiprocessing import Process, Queue

def f(q):
    q.put([42,None,'hi'])

if __name__ == '__main__':
    q = Queue()
    p = Process(target=f, args=(q,))
    p.start()
    print q.get()  #打印内容: [42,None,'hi']
    p.join()

二、Pipe類別

pipe()函數傳回一對物件的連接,可以為進程間傳輸訊息,在列印一些日誌、進程控制上面有一些用處,Pip()物件會傳回兩個對象connection,代表兩個通道,每個connection物件都有send()和recv()方法,需要注意的是兩個或更多的進程同時讀取或寫入同一管道,可能會導致資料混亂,測試了下,是直接覆蓋了。另外,回傳的兩個connection,如果一個是send()資料,那麼另外一個就只能recv()接收資料了

#-*- coding:utf8 -*-
from multiprocessing import Process, Pipe
import time
def f(conn,i):
    print '[{0}]已经执行到子进程:{1}'.format(time.ctime(),i)
    time.sleep(1)
    w = "[{0}]hi,this is :{1}".format(time.ctime(),i)
    conn.send(w)
    conn.close()

if __name__ == '__main__':
    reader = []
    parent_conn, child_conn = Pipe()
    for i in range(4):
        p = Process(target=f, args=(child_conn,i))
        p.start()
        reader.append(parent_conn)
        p.deamon=True

    # 等待所有子进程跑完
    time.sleep(3)
    print '\n[{0}]下面打印child_conn向parent_conn传输的信息:'.format(time.ctime())
    for i in reader:
        print i.recv()

輸出為:


三、Value,Array

在进行并发编程时,应尽量避免使用共享状态,因为多进程同时修改数据会导致数据破坏。但如果确实需要在多进程间共享数据,multiprocessing也提供了方法Value、Array

from multiprocessing import Process, Value, Array

def f(n, a):
    n.value = 3.1415927
    for i in range(len(a)):
        a[i] = -a[i]

if __name__ == '__main__':
    num = Value('d',0.0)
    arr = Array('i', range(10))

    p = Process(target=f, args=(num, arr))
    p.start()
    p.join()

    print num.value
    print arr[:]

*print
3.1415927
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]*

四、Manager进程管理模块

Manager类管理进程使用得较多,它返回对象可以操控子进程,并且支持很多类型的操作,如: list, dict, Namespace、lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value, Array,因此使用Manager基本上就够了

from multiprocessing import Process, Manager

def f(d, l):
    d[1] = '1'
    d['2'] = 2
    d[0.25] = None
    l.reverse()

if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict()
        l = manager.list(range(10))

        p = Process(target=f, args=(d, l))
        p.start()
        p.join() #等待进程结束后往下执行
        print d,'\n',l

输出:
{0.25: None, 1: '1', '2': 2}
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
可以看到,跟共享数据一样的效果,大部分管理进程的方法都集成到了Manager()模块了

五、对多进程控制的应用实例

    #-*- coding:utf8 -*-
    from multiprocessing import Process, Queue
    import time
    
    def work(pname,q):
        time.sleep(1)
        print_some = "{0}|this is process: {1}".format(time.ctime(),pname)
        print print_some
        q.put(pname)
    
    if __name__ == '__main__':
        p_manag_num = 2  # 进程并发控制数量2
        # 并发的进程名
        q_process = ['process_1','process_2','process_3','process_4','process_5']
        q_a = Queue() # 将进程名放入队列
        q_b = Queue() # 将q_a的进程名放往q_b进程,由子进程完成
    
        for i in q_process:
            q_a.put(i)
    
        p_list = [] # 完成的进程队列
        while not q_a.empty():
            if len(p_list) <p>执行结果:</p><p><img src="https://img.php.cn//upload/image/167/872/710/1542261551928622.png" title="1542261551928622.png" alt="python多進程控制的教學講解(附範例)"></p>

以上是python多進程控制的教學講解(附範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:https://segmentfault.com/a/1190000016855803。如有侵權,請聯絡admin@php.cn刪除

相關文章

看更多