2017-10-15 98 views
0

早些時候,我嘗試在python中使用線程模塊來創建多個線程。然後我瞭解了GIL以及它如何不允許在一臺機器上利用多個CPU內核。所以現在我試圖做多處理(我不嚴格需要單獨的線程)。使用Python產生多個進程

這是我寫的示例代碼,以查看是否正在創建不同的進程。但是從下面的輸出中可以看出,我每次都得到相同的進程ID。所以多個進程沒有被創建。我錯過了什麼?

import multiprocessing as mp 
import os 

def pri(): 
    print(os.getpid()) 

if __name__=='__main__': 

    # Checking number of CPU cores 
    print(mp.cpu_count()) 

    processes=[mp.Process(target=pri()) for x in range(1,4)] 

    for p in processes: 
     p.start() 

    for p in processes: 
     p.join() 

輸出:

4 
12554 
12554 
12554 
+2

刪除第在'target = pri()'上輸入e'()' –

回答

2

Process類需要一個可調用作爲其目標。

而不是在單獨的進程中運行該函數,而是調用它並將結果(本例中爲None)傳遞到Process類。

只需更改如下:

mp.Process(target=pri()) 

有:

mp.Process(target=pri) 
+0

這仍然返回相同的PID。它甚至不會將它打印到屏幕上,因爲它在子進程中運行。 – Vinny

+0

我剛剛嘗試了代碼,我得到3個不同的PID。取決於操作系統,它可能會重新使用PID,在這種情況下,它與OP無關,因爲範圍是測試'multiprocessing'庫。 – noxdafox

0

由於子進程運行在不同的過程中,你不會看到他們的打印報表。他們也不共享相同的內存空間。你傳遞pri()到目標,它需要pri。您需要通過一個可調用對象,而不是執行它。

您看到的打印件是主線程執行的一部分。因爲您通過pri(),代碼實際上執行。您需要更改代碼,以便pri函數返回值,而不是打印它。

然後,你需要實現一個queue,其中所有的線程它和他們做的時候,你的主線程讀取隊列。

multiprocessing模塊的一個很好的功能是Pool對象。它允許你創建一個線程池,然後使用它。這更方便。

我試過了你的代碼,事情是該命令執行得太快,所以操作系統重用了PID。如果您在pri函數中添加time.sleep(1),它將按您的預期工作。

這僅適用於Windows。下面的例子是在Windows平臺上進行的。在Unix上像機器一樣,你不需要睡眠。

更方便的解決方案是這樣的:

from multiprocessing import Pool 
from time import sleep 
import os 

def pri(x): 
    sleep(1) 
    return os.getpid() 

def use_procs(): 
    p_pool = Pool(4) 
    p_results = p_pool.map(pri, [_ for _ in range(1,4)]) 
    p_pool.close() 
    p_pool.join() 
    return p_results 

if __name__ == '__main__': 
    res = use_procs() 
    for r in res: 
     print r 

如果沒有睡眠:

==================== RESTART: C:/Python27/tests/test2.py ==================== 
6576 
6576 
6576 
>>> 

與睡眠:

==================== RESTART: C:/Python27/tests/test2.py ==================== 
10396 
10944 
9000 
+0

如果您使用「Pool」,任務將由第一個可用工作人員處理。由於Windows使用'spawn'啓動方法,進程的啓動速度比Unix(默認情況下使用'fork')慢。因此,第一個員工流程在其他員工準備好之前「搶走」了所有任務。這就是爲什麼你看到只有第一個PID被打印在你的邏輯中。 – noxdafox

+0

你說得對。我只是在Linux機器上嘗試過它,它確實打印了唯一的PID。但是,除了打印之外,爲了使進程與主線程通信,它必須使用通信接口(隊列,套接字等)。使用'Pool'可以簡化多處理過程。 – Vinny

+0

這取決於用例,有時你只需要旋轉諸如HTTP服務器之類的東西。在這些情況下,你並不關心函數返回的內容。對於許多用例來說,進程都是很好的,我個人最喜歡的是他們提供給應用程序的隔離。如果另一個進程中的邏輯崩潰,您的應用程序將不受影響。使用線程或協程無法輕鬆實現這一點。 – noxdafox

相關問題