Python 並行處理完整指南|高效實作方法與應用範例

1. 簡介

Python 並行處理的重要性

Python 作為一種簡單且易於使用的程式語言,被廣泛應用於各種領域。然而,當涉及複雜的資料處理或運算時,Python 的執行速度可能成為一個挑戰。為了解決這個問題,「並行處理」發揮了重要作用,讓多個任務可以同時執行。本文將介紹如何在 Python 中實作並行處理,從基本方法到實際應用案例,幫助您提升程式的執行效率。

2. Python 的並行處理方法

主要的並行處理方式

在 Python 中,有幾種方法可以實現並行處理,主要包括以下三種:

  1. 多執行緒 (threading 模組)
    使用多個執行緒來並行執行任務,但由於 Python 的 GIL(全域解釋器鎖,Global Interpreter Lock)限制,對於 CPU 密集型的任務,效果可能有限。
  2. 多進程 (multiprocessing 模組)
    每個進程擁有獨立的記憶體空間,因此不受 GIL 限制,可以實現真正的並行運算。特別適合大規模資料處理或高計算量的任務。
  3. 非同步處理 (asyncio 模組)
    適用於 I/O 密集型任務(如網路請求或檔案操作),可透過非同步執行來提升效率,使等待時間較長的處理能更有效率地進行。

年収訴求

3. 多進程 vs 多執行緒

GIL(全域解釋器鎖)的影響

Python 具有 GIL(Global Interpreter Lock,全域解釋器鎖)機制,這意味著在單個 Python 直譯器內,同一時間只能執行一個執行緒。這導致在 CPU 密集型任務中,即使增加執行緒數量,也無法顯著提升效能。因此,多執行緒的並行處理主要適用於 I/O 密集型任務,而非 CPU 密集型任務。

多執行緒的優勢與限制

多執行緒相對較輕量,適合處理 I/O 密集型任務(如檔案操作、網路請求等)。然而,由於 GIL 的影響,它無法有效利用多核心 CPU,因此對於 CPU 密集型運算的應用較為有限。

“`
import threading
import time

def worker(num):
print(f”Worker {num} starting”)
time.sleep(2)
print(f”Worker {num} finished”)

threads = [] for i in range(5):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()

for t in threads:
t.join()
“`

上面的程式碼同時執行 5 個執行緒,每個執行緒會執行 2 秒後結束。雖然這讓任務看起來是並行執行的,但實際上,它們仍受 GIL 限制。

多進程的優勢

為了繞過 GIL 限制,多進程(Multiprocessing)是一個更好的解決方案。進程與執行緒不同,每個進程擁有獨立的記憶體空間,能夠充分利用多核心 CPU,特別適用於大量計算或大規模資料處理。

“`
from multiprocessing import Process
import time

def worker(num):
print(f”Worker {num} starting”)
time.sleep(2)
print(f”Worker {num} finished”)

if name == ‘main‘:
processes = [] for i in range(5):
p = Process(target=worker, args=(i,))
processes.append(p)
p.start()

for p in processes:
    p.join()

“`

在這個例子中,5 個進程會獨立運行,它們彼此不受影響,並且能夠同時利用多個 CPU 核心來執行任務。

4. Python 並行處理的實作方法

使用 multiprocessing 模組

multiprocessing 模組提供了許多強大的功能,可以有效管理多個進程。例如,我們可以使用「進程池(Process Pool)」來自動分配任務,使程式能夠高效執行。

“`
from multiprocessing import Pool

def square(x):
return x * x

if name == ‘main‘:
with Pool(4) as p:
result = p.map(square, [1, 2, 3, 4, 5])
print(result)
“`

此程式碼使用 4 個進程來計算平方值,並將結果以列表形式返回。這種方式能夠有效提升運算效率。

侍エンジニア塾

5. 非同步處理及其應用

使用 asyncio 進行非同步處理

非同步處理適用於 I/O 密集型的任務,例如網路請求、資料庫查詢或檔案讀寫等。asyncio 模組允許 Python 透過「協程」來執行非同步任務,使程式在等待某些操作(如網路請求)時,能夠同時執行其他任務,提升效能。

“`
import asyncio

async def worker(num):
print(f’Worker {num} starting’)
await asyncio.sleep(1)
print(f’Worker {num} finished’)

async def main():
tasks = [worker(i) for i in range(5)] await asyncio.gather(*tasks)

asyncio.run(main())
“`

這段程式碼建立 5 個非同步任務,每個任務執行 1 秒後結束。在執行期間,Python 會在等待(sleep)時自動切換到其他任務,確保 CPU 不會閒置,提高運行效率。


6. 並行處理的效能調校

使用 Joblib 進行並行化

Joblib 是一個專門用於並行計算的 Python 函式庫,特別適用於數據處理和機器學習的訓練過程。使用 Joblib 可以輕鬆地讓 Python 程式多核心並行執行,提高計算效率。

“`
from joblib import Parallel, delayed

def heavy_task(n):
return n ** 2

results = Parallel(n_jobs=4)(delayed(heavy_task)(i) for i in range(10))
print(results)
“`

在這段程式碼中,透過 n_jobs=4 指定同時執行 4 個進程,並對數字 0-9 進行平方計算。這種方式在數據分析、機器學習等場景中特別有用。

RUNTEQ(ランテック)|超実戦型エンジニア育成スクール

7. Python 並行處理的實際應用

數據處理與 Web 爬取

在數據處理或 Web 爬取等應用中,並行處理可以顯著提高效率。例如,在爬取大量網頁時,使用多執行緒或非同步處理可以同時發送多個請求,大幅減少總處理時間。

例如,使用 requeststhreading 進行多執行緒的 Web 爬取:

“`
import threading
import requests

def fetch_url(url):
response = requests.get(url)
print(f”Fetched {url} with status {response.status_code}”)

urls = [
“https://example.com/page1”,
“https://example.com/page2”,
“https://example.com/page3”
]

threads = [] for url in urls:
t = threading.Thread(target=fetch_url, args=(url,))
threads.append(t)
t.start()

for t in threads:
t.join()
“`

這段程式碼會同時請求 3 個網頁,並透過多執行緒方式加快請求速度。

8. 總結

並行處理是提升 Python 程式執行效能的重要技術。根據不同的應用場景,可以選擇合適的方法:

  • threading:適用於 I/O 密集型任務,例如檔案處理和網路請求。
  • multiprocessing:適用於 CPU 密集型運算,例如數據處理和科學計算。
  • asyncio:適用於非同步 I/O 操作,例如網路爬取和 API 請求。
  • Joblib:適用於機器學習和大規模數據運算。

透過合理選擇並行處理技術,可以有效提高 Python 程式的效能,讓應用更快、更高效地運行。