【Python併發】【Python多進程(一)】創建進程
【Python併發】【Python多進程(二)】進程間通信
【Python併發】【Python多進程(三)】進程間數據共享
【Python併發】【Python多進程(四)】進程同步
一. 多進程模塊multiprocessing
在Python的os模塊中封裝了許多的系統調用,其中封裝了Unix/Linux系統中的fork()系統調用,其作用是複製當前的進程來產生新進程,當前進行稱爲“父進程”,新進程稱爲“子進程”。但是,在Windows系統中是沒有fork()系統調用的。因此,Python提供了跨平臺的多進行模塊"multiprocessing"。
二. 使用Process類創建進程
2.1 直接使用Process類
from multiprocessing import Process
def say_hi(name):
print('hi', name+'!')
if __name__ == '__main__':
p = Process(target=say_hi, args=('tony',)) # 指定進程執行的函數並傳遞參數
p.start() # 啓動進程
p.join() # 使主進程等待子進程(也就是定義的p)結束後運行,用於進程同步
輸出:
hi tony!
2.2 繼承Process類
from multiprocessing import Process
class MyProcess(Process):
def __init__(self, name):
super(MyProcess, self).__init__()
self.name = name
def run(self): # 重寫父類的run()方法,其中應包含進程將要執行的代碼
print('hi', self.name + '!')
if __name__ == '__main__':
p = MyProcess('tony')
p.start()
p.join()
輸出:
hi tony!
2.3 進階例子:顯示進程信息
from multiprocessing import Process
import os
def process_info(message):
print(message)
print('當前模塊:', __name__)
print('當前進程的父進程id: ', os.getppid())
print('當前進程的id: ', os.getpid())
def say_hi(name):
process_info('say_hi')
print('hi', name+'!')
if __name__ == '__main__':
p = Process(target=say_hi, args=('tony',))
p.start()
p.join()
輸出:
say_hi
當前模塊: __mp_main__
當前進程的父進程id: 22300
當前進程的id: 15624
hi tony!
2.4 Porcess對象常用的方法與屬性
- name:進程的名稱;
- daemon:布爾值,是否是守護進程;
- pid:進程ID;
- exitcode:進程退出碼;
- run():表示進程所要做的事情,通過向參數taget指定一個函數的方式指定run的行爲,或者在子類中重載該方法;
- start():啓動進程;
- join():阻塞當前進程,直至調用該方法的進程結束;
- is_alive():判斷進程是否還活着;
- terminate():終止進程;
- close():關閉Process對象,釋放與之關聯的資源;
from multiprocessing import Process
import time
import signal
p = Process(target=time.sleep, args=(10, ))
print(p, p.is_alive()) # <Process(Process-1, initial)> False
p.start()
print(p, p.is_alive()) # <Process(Process-1, started)> True
p.terminate()
time.sleep(1)
print(p, p.is_alive()) # <Process(Process-1, stopped[SIGTERM])> False
print(p.exitcode == -signal.SIGTERM) # True
2.5 進程池Pool
進程池用於批量的創建進程
from multiprocessing import Pool
import os
def square(x):
return x**2
if __name__ == '__main__':
print('父進程:{}'.format(os.getppid()))
with Pool(processes=4) as pool: # 指定進程池中包含的進程數
print(pool.apply(square, (2,))) # 阻塞式調用
res1 = pool.apply_async(square, (3,)) # 異步調用
print(res1.get(timeout=2)) # 獲得返回值,2秒內未返回則拋異常
# 啓動多個異步進程
multiple_results = [pool.apply_async(square, (i,)) for i in range(3)]
print([res.get(timeout=1) for res in multiple_results])
print(pool.map(square, range(3))) # map的並行版本
for i in pool.imap(square, range(3)): # pool.map的迭代器版本
print(i)
for i in pool.imap_unordered(square, range(3)): # imap的無序版本
print(i)
pool.close()
pool.join() # join()只能在close()後調用,因此pool.close()後表示不再接受新的進程了
print("所有子進程結束!")