1. 問題引出
許多時候,我們對程式的速度都是有要求的,速度自然是越快越好。對於python的話,一般都是使用multiprocessing這個庫來實現程式的多程序化,例如:
我們有乙個函式my_print,它的作用是列印我們的輸入:
def my_print(x):
print(x)
但是我們嫌它的速度太慢了,因此我們要將這個程式多程序化:
from multiprocessing import pool
def my_print(x):
print(x)
if __name__ == "__main__":
x = [1, 2, 3, 4, 5]
pool = pool()
pool.map(my_print, x)
pool.close()
pool.join()
很好,現在速度與之前的單程序相比提公升非常的快,但是問題來了,如果我們的引數不只有乙個x,而是有多個,這樣能行嗎?比如現在my_print新增乙個引數y:
def my_print(x, y):
print(x + y)
檢視pool.map的函式說明:
def map(self, func, iterable, chunksize=none):
'''apply `func` to each element in `iterable`, collecting the results
in a list that is returned.
'''return self._map_async(func, iterable, mapstar, chunksize).get()
發現函式的引數是作為iter傳進去的,但是我們現在有兩個引數,自然想到使用zip將引數進行打包:
if __nameqyyubvhob__ == "__main__":
x = [1, 2, 3, 4, 5]
y = [1, 1, 1, 1, 1]
zip_args = list(zip(x, y))
pool = pool()
pool.map(my_print, zip_args)
pool程式設計客棧.close()
pool.join()
可是執行後卻發現,y引數並沒有被傳進去:
那麼如何傳入多個引數呢?這也就是本文的重點,接著往下看吧。
2. 解決方案
2.1 使用偏函式(partial)
偏函式有點像數學中的偏導數,可以讓我們只關注其中的某乙個變程式設計客棧量而不考慮其他變數的影響。上面的例子中,y始終等於1,那麼我們在傳入引數的時候,只需要考慮x的變化即可。
例如你有乙個函式,該函式有兩個引數a,b,a是不同路徑的下的的路徑,b是輸出的路徑。很明顯,a是一直在變化的,但是因為我們要將所有儲存在同乙個資料夾下,那麼b很可能一直都沒變。
具體如下:
if __name__ == '__main__':# 多執行緒,多引數,partial版本
x = [1, 2, 3, 4, 5]
y = 1
partial_func = partial(my_print, y=y)
pool = pool()
pool.map(partial_func, x)
pool.close()
pool.join()
2.2 使用可變引數
在python函式中,函式可以定義可變引數。顧名思義,可變引數就是傳入的引數個數是可變的,可以是1個、2個到任意個,這就直接給我們提供了一種思路。具體如下:
def multi_wrapper(args):
return my_print(*args)
def my_print(x, y):
print(x + y)
if __name__ == "__main__": # 多執行緒,多引數,可變引數版本
x = [1, 2, 3, 4, 5]
y = [1, 1, 1, 1, 1]
zip_args = list(zip(x, y))
pool = pool()
pool.map(multi_wrapper, zip_args)
pool.close()
pool.join()
2.3 使用pathos提供的多程序庫
from pathos.multiprocessing i程式設計客棧mport processingpool as newpool
if __name__ == '__main__':# 多執行緒,多引數,pathos版本
x = [1, 2, 3, 4, 5]
y = [1, 1, 1, 1, 1]
pool = newpool()
pool.map(my_print, x, y)
pool.close()
pool.join()
在該庫的map函式下,可以看到,它允許多引數輸入,其實也就是使用了可變引數:
def map(self, f, *args, **kwds):
abstractworkerpool._abstractworkerpool__map(self, f, *args, **kwds)
_pool = self._serve()
return _pool.map(star(f), zip(*args)) # chunksize
2.4 使用starmap函式
if __name__ == '__main__': # 多執行緒,多引數,starmap版本
x = [1, 2, 3, 4, 5]
y = [1, 1, 1, 1, 1]
zip_args = list(zip(x, y))
pool = pool()
pool.starmap(my_print, zip_args)
pool.close()
pool.join()
3. 總結
其實在以qyyubvhob上4種實現方法中 ,第1種方法的限制較多,如果該函式的其它引數都在變化的話,那麼它就不能很好地工作,而剩下的方法從體驗上來講是依次遞增的,它們都可以接受任意多引數的輸入,但是第2種需要額外寫乙個函式,扣分;第3種方法需要額外安裝pathos包,扣分;而最後一種方法不需要任何額外不擇就可以完成,所以,推薦大家選擇第4種方法!
本文標題: python使用多程序執行含有任意個引數的函式
本文位址:
python使用多程序
python多執行緒適合io密集型場景,而在cpu密集型場景,並不能充分利用多核cpu,而協程本質基於執行緒,同樣不能充分發揮多核的優勢。針對計算密集型場景需要使用多程序,python的multiprocessing與threading模組非常相似,支援用程序池的方式批量建立子程序。只需要例項化pr...
python多程序 python多程序
當有多個非相關任務需要處理時,並行能大大提高處理速度。這裡簡要介紹python的multiprocessing模組。簡單多程序編寫 當我們任務數量確定而且比較少的時候,可以手動為每個任務指定乙個程序來執行。import multiprocessing as mp def f a print a if...
python定時執行,多程序
可以通過另開一條執行緒,去專門做這件事情,py2 如下,如果是py3請自行調整下語法 coding utf8 import threading import time 真正要執行的函式 def t1 print ok 每隔10秒鐘執行 def t2 while 1 t1 time.sleep 10 ...