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')
下面是執行截圖:
我們添加了七個任務,但程序池隻有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')
下面是執行截圖:
若有問題請關注微信公衆号"夜寒資訊"
微信關注公衆号:夜寒資訊
緻力于為每一位使用者免費提供更優質技術幫助與資源供給,感謝支援!