Python3中multiprocessing的Process創建子進程在Windows和Linux下的區別
結論:
儘量在Linux中使用多進程,Linux中更遵循程序設計之初的規範。
比如實例1中,Windows是全代碼重頭運行,無法共享父進程全局變量,全局變量會重新建立,Linux則是按照規矩僅從函數段運行。
比如實例2-2中,Windows下使用多進程,將全局變量作爲參數傳遞,可以解決由於代碼執行控製造成的子進程和父進程是無法共享一個對象的問題。
實例1:
# -*- coding: utf-8 -*-
import multiprocessing as mp
from time import sleep
import os
a = 1
print("[父/子] PID", os.getpid(), a, "===================")
def fun(xx): # 進程事件
sleep(1)
global a
print("[子]", "-----------------", a)
print("[子]", "子進程事件")
print("[子]", "傳入內容:", xx)
print("[子]", 'PID', os.getpid())
a = 10000
print("[子]", "-----------------", a)
# windows下運行需要此句判斷,否則報錯,Linux下無需
if __name__ == "__main__":
print("[父]", 'PPID', os.getpid())
p = mp.Process(target=fun, args=('test',)) # 創建進程對象
p.start() # 啓動進程
print("[父]", "這是父進程")
p.join() # 回收進程
print("[父]", "===================", a)
windows運行結果:
[父/子] PID 9272 1 ===================
[父] PPID 9272
[父] 這是父進程
[父/子] PID 22788 1 ===================
[子] ----------------- 1
[子] 子進程事件
[子] 傳入內容: test
[子] PID 22788
[子] ----------------- 10000
[父] =================== 1
Linux運行結果:
[父/子] PID 36 1 ===================
[父] PPID 36
[父] 這是父進程
[子] ----------------- 1
[子] 子進程事件
[子] 傳入內容: test
[子] PID 37
[子] ----------------- 10000
[父] =================== 1
結果中,Windows下運行[父/子] PID 22788 1 ===================
多打印了。
由此可見,Windows是全代碼重頭運行,無法共享父進程全局變量,全局變量會重新建立,Linux則是按照規矩僅從函數段運行。
實例2-1:
from multiprocessing import Process, Array
import time
# 創建共享內存,存入列表
shm = Array('i', [1,2,3,4,5])
# shm = Array('i', range(5))
# shm = Array('i', 5) # 表示開闢5個空間
def fun():
# shm 是可迭代對象
for i in shm:
print(i)
# 修改共享內存
print(list(shm))
shm[3] = 1000
if __name__ == '__main__':
p = Process(target=fun)
p.start()
p.join()
print("=================")
for i in shm:
print(i)
Windows下運行結果:
1
2
3
4
5
[1, 2, 3, 4, 5]
=================
1
2
3
4
5
Linux下運行結果:
1
2
3
4
5
[1, 2, 3, 4, 5]
=================
1
2
3
1000
5
由此實例可見,Windows下程序並未報錯,且未達到我們運行的效果——修改共享內存中的第4位數爲1000。
實例2-2:
from multiprocessing import Process, Array
import time
# 創建共享內存,存入列表
shm = Array('i', [1,2,3,4,5])
# shm = Array('i', range(5))
# shm = Array('i', 5) # 表示開闢5個空間
def fun(shm):
# shm 是可迭代對象
for i in shm:
print(i)
# 修改共享內存
print(list(shm))
shm[3] = 1000
if __name__ == '__main__':
p = Process(target=fun, args=(shm,))
p.start()
p.join()
print("=================")
for i in shm:
print(i)
由此可見,如果要在Windows下使用多進程,最好將全局變量作爲參數傳遞,子進程和父進程是無法共享一個對象的。
實例2-3:
from multiprocessing import Process, Array
import time
def fun(shm):
# shm 是可迭代對象
for i in shm:
print(i)
# 修改共享內存
print(list(shm))
shm[3] = 1000
if __name__ == '__main__':
# 創建共享內存,存入列表
# shm = Array('i', [1,2,3,4,5])
shm = Array('i', range(5))
# shm = Array('i', 5) # 表示開闢5個空間
p = Process(target=fun, args=(shm,))
p.start()
p.join()
print("=================")
for i in shm:
print(i)
Windows下和Linux下運行結果皆爲:
0
1
2
3
4
[0, 1, 2, 3, 4]
=================
0
1
2
1000
4
當然,該寫法和上一個實例一樣的效果。都是將全局變量作爲參數傳遞給需要多進程的函數了