Pythonでは、`concurrent.futures` モジュールを使用して並行処理を行うことができます。この記事では、基本的な使い方からより高度な応用例まで、`concurrent.futures` で可能な並行処理の手法について詳しく解説します。
なぜ並行処理なのか?
並行処理は、同時に複数のタスクを実行する手法です。これにより、プログラムの効率が向上し、リソースを最大限に活用することが可能になります。特に、I/OバウンドやCPUバウンドな作業を高速化するのに非常に有用です。
並行処理と並列処理
一般的に、並行処理と並列処理はよく混同されますが、実は異なる概念です。並行処理はマルチタスクを効率的に管理する一方、並列処理は複数のプロセッサを使って同時にタスクを実行します。
concurrent.futuresの基本
Pythonの標準ライブラリである`concurrent.futures`は、非同期実行を抽象化したインターフェースを提供します。主に`ThreadPoolExecutor`と`ProcessPoolExecutor`の2つのクラスがあります。
ThreadPoolExecutorとProcessPoolExecutor
`ThreadPoolExecutor`はスレッドベース、`ProcessPoolExecutor`はプロセスベースの並行処理を実現します。一般に、I/Oバウンドな作業は`ThreadPoolExecutor`、CPUバウンドな作業は`ProcessPoolExecutor`が適しています。
基本的な使い方
以下は、`concurrent.futures`を用いた基本的なコード例です。
from concurrent.futures import ThreadPoolExecutor
import time
def task_function(x):
time.sleep(2)
return x * 2
# スレッドプールを作成
with ThreadPoolExecutor() as executor:
# 非同期にタスクを実行
future = executor.submit(task_function, 10)
# 結果を取得
result = future.result()
print("Result:", result)
このコードは、`task_function`という関数を非同期で実行し、その結果を取得しています。
応用例1:マップ関数を使用した一括処理
`concurrent.futures`には`map`関数があり、複数の引数を一括で処理することができます。
from concurrent.futures import ThreadPoolExecutor
def task_function(x):
return x * 2
with ThreadPoolExecutor() as executor:
results = list(executor.map(task_function, [1, 2, 3, 4, 5]))
print("Results:", results)
このコードは、リストの各要素に`task_function`を適用し、その結果をリストとして返しています。
応用例2:例外処理の組み込み
`concurrent.futures`を用いた非同期処理では、例外を適切にハンドリングすることも重要です。
from concurrent.futures import ThreadPoolExecutor
def task_function(x):
if x == 2:
raise ValueError("x should not be 2")
return x * 2
with ThreadPoolExecutor() as executor:
future = executor.submit(task_function, 2)
try:
result = future.result()
except ValueError as e:
print("Caught an exception:", e)
このコードは、`task_function`内で特定の条件下で例外を発生させ、その例外を`future.result()`メソッドでキャッチしています。
まとめ
`concurrent.futures`モジュールは、Pythonで並行処理を効率的に行う強力なツールです。基本的な使い方から例外処理、高度な処理手法まで、多くの機能を提供しています。この記事を通じて、より効率的なプログラムを作成できるようになれば幸いです。
コメント