天天看點

Python程序池及自定義程序Python程序池及自定義程序

Python程序池及自定義程序

微信關注公衆号:夜寒資訊

緻力于為每一位使用者免費提供更優質技術幫助與資源供給,感謝支援!

  這次給大家分享Python的程序池及自定義程序,由于Python基礎已經講述,不再贅述類,方法,及其他基礎文法的概念。多程序在任務的執行使用非常廣泛,比如Windows可以同時開很多的視窗,QQ,微信,遊戲等。以後我們也會講解多線程,多線程常用于下載下傳,以後會有講解。

一、程序重寫

  首先我們按照正常導入multiprocessing子產品,同樣我們使用

from multiprocessing import Process

語句來導入Process類。還記得上篇文章寫的run()方法嗎(Python的多程序運作)要重寫程序,就要重寫run()方法。

  如果我們我們要自定義一個程序,那麼我們就需要在建立我們自己的類時繼承父類的Process方法:

class MyProcess(Process):
	def run(self):
		pass
           

  這樣我們便完成了程序自定義的結構,Process父類的東西都可以在我們的自定義程序内使用。我們可以使用一個例子,來給大家講解。

  假設我們建立兩個程序,循環列印所傳入的參數并計數,每執行一次程序加一,我們所需要實作的代碼如下:

class MyProcess(Process):
    def run(self):
        n = 1
        while True:
            print('程序名:{} n的值:{}'.format(self.name, n))
            n += 1
           

  每當我們使用start()方法時,系統都會先進入Process類中找run()方法,通過run()方法來啟動程序。我們再來添加一個主函數,建立兩個程序對象,并将他們添加到程序中:

if __name__ == '__main__':
    p1 = MyProcess(name='李諾')
    p2 = MyProcess(name='夜寒')
    p1.start()
    p2.start()
           

  這是我們運作程式,變發現程式按照我們的需求進行。下附完整代碼:

# 程序:自定義
from multiprocessing import Process


class MyProcess(Process):
    # 重寫run()方法

    def run(self):
        n = 1
        while True:
            print('程序名:{} n的值:{}'.format(self.name, n))
            n += 1


if __name__ == '__main__':
    p1 = MyProcess(name='李諾')
    p2 = MyProcess(name='夜寒')
    p1.start()
    p2.start()
           

二、程序池

  下面我們程序池,當我們需要建立成百上千的程序時,僅僅手動建立則會非常麻煩,于是我們來使用程序池。我們使用

from multiprocessing import Pool

來調用程序池,使用

Pool()

方法來建立程序池,并定義最大程序數。程序池分為阻塞式和非阻塞式,我們一一講解。

一、非阻塞式程序池

首先我們需要導入這幾個庫:

import os
import time
from multiprocessing import Pool
from random import random
           

  首先我們建立一個任務。我們先傳入一個任務名,我們使用random和sleep方法來模拟做任務的時間,再使用time來獲得做任務的耗時使用os庫來獲得人物的pid和ppid。最後再傳回我們做任務的結果,以下是實作的代碼:

def task(task_name):
    start = time.time()
    time.sleep(random() * 2)
    end = time.time()
    return '完成{},用時:{},程序ID:{}'.format(task_name, (end-start), os.getpid())
           

  接下來我們再建立主函數,先建立程序池,再建立一個清單,裡面添加自己所需的程序。我們使用

pool.apply_async()

來将程序添加到程序池,下面附上實作代碼:

if __name__ == '__main__':
    pool = Pool(5)
    tasks = ['聽音樂', '打遊戲', '洗衣服', '去散步', '去學習', '上廁所', '打代碼']
    for i in tasks:
        pool.apply_async(task, args=(i,), callback=call_back)

    pool.close()
    pool.join()
    print('OVER')
           

  其中,pool.close()是表示添加任務結束,需要在添加完任務後在主程序加入此語句。程序池的運作必須要添加pool,join()方法,它可以堵住主程序,使程序池的任務全部執行完成之後才能結束主程序。程序池的運作依賴于主程序,主程序運作完程序池内的任務便會結束,是以添加pool.join(),否則添加完任務後不運作便會結束。

  我們再來了解回調方法

callback

它會将程序(

task()

)的傳回值接收,并傳入回調函數,回調函數再進行處理。我們定義一個call_back()函數,用來充當callback的參數,實作代碼如下:

def call_back(n):
    print(n)
           

  回調函數必須傳入參數(上述代碼中

n

)我們列印n的值也就是task()的傳回值。以下是全部代碼:

# 非阻塞式:全部添加到隊列中,立即傳回,并未等待其他程序執行完畢,但是回調函數等待任務完成後才調用
# 程序池
import os
import time
from multiprocessing import Pool
from random import random


# 非阻塞式程序
def task(task_name):
    # print('開始任務:', task_name)
    start = time.time()
    time.sleep(random() * 2)
    end = time.time()
    return '完成{},用時:{},程序ID:{}'.format(task_name, (end-start), os.getpid())


def call_back(n):
    print(n)


if __name__ == '__main__':
    pool = Pool(5)
    tasks = ['聽音樂', '打遊戲', '洗衣服', '去散步', '去學習', '上廁所', '打代碼']
    for i in tasks:
        pool.apply_async(task, args=(i,), callback=call_back)

    pool.close()    # 添加表示任務結束
    pool.join()     # 堵住主程序,完成任務之後可繼續執行主程序
    print('OVER')
           

下面是執行截圖:

Python程式池及自定義程式Python程式池及自定義程式

  我們添加了七個任務,但程序池隻有5個空位。于是系統在添加程序時,未被添加的任務會等待,當其他任務執行完有空位後它在被添加。其中,系統在執行任務時,會從程序池中同時随機選取任務執行,可以看任務名稱,不是按清單順序執行,這便是非阻塞式程序池。

一、非阻塞式程序池

  阻塞式程序池隻需将

pool.apply_async()

改為

pool.apply()

即可。其中,系統在執行任務時,會按序從程序池中選取任務執行,可以看任務名稱,當第一個任務未執行完時下一個任務不會被執行。這樣雖然不會造成任務執行不按序而沖突,但會大大加長任務的執行時間,效率低下。以下附上實作需求的所有代碼,這便是阻塞式程序池。

'''
 特點:
 添加一個任務執行一個任務,如果一個任務不結束,另一個任務就進不來

 程序池:
 pool = Pool(max)   建立程序池對象
 pool.apply()       阻塞的
 pool.apply_async() 非阻塞的

 pool.close()   執行結束後關閉程序
 pool.join()    讓主程序讓步
'''

import os
import time
from multiprocessing import Pool
from random import random


# 非阻塞式程序
def task(task_name):
    # print('開始任務:', task_name)
    start = time.time()
    time.sleep(random() * 2)
    end = time.time()
    print('完成{},用時:{},程序ID:{}'.format(task_name, (end-start), os.getpid()))


def call_back(n):
    print(n)


if __name__ == '__main__':
    pool = Pool(5)
    tasks = ['聽音樂', '打遊戲', '洗衣服', '去散步', '去學習', '上廁所', '打代碼']
    for i in tasks:
        pool.apply(task, args=(i,))

    pool.close()    # 添加表示任務結束
    pool.join()     # 堵住主程序,完成任務之後可繼續執行主程序
    print('OVER')
           

下面是執行截圖:

Python程式池及自定義程式Python程式池及自定義程式

若有問題請關注微信公衆号"夜寒資訊"

  

微信關注公衆号:夜寒資訊

緻力于為每一位使用者免費提供更優質技術幫助與資源供給,感謝支援!