この記事では、Pythonでの並行・並列処理とモジュールインポートについて詳しく説明します。具体的なコード例とその解説、応用例を含めて、どのようにPythonの並行・並列処理が行われ、どうモジュールインポートが影響するのかを理解するためのガイドです。
並行処理と並列処理の基礎
並行処理とは、一つのプログラムが多数のタスクを処理する技術です。並列処理は、それらのタスクが同時に処理される特殊な形態です。並行処理は主にI/Oバウンドな作業に、並列処理はCPUバウンドな作業に適しています。
並行処理の実例
Pythonでの並行処理は主に`threading`と`asyncio`によって実現されます。以下は`threading`を使用した簡単な例です。
import threading
def print_numbers():
for i in range(10):
print(i)
# スレッドの作成と開始
thread = threading.Thread(target=print_numbers)
thread.start()
# 主スレッドでの処理
print("This is the main thread.")
# スレッドが終了するのを待つ
thread.join()
このコードでは、`print_numbers`関数が新しいスレッドで実行され、主スレッドはその間にも別の処理を行います。
並列処理の実例
並列処理は主に`multiprocessing`モジュールで実現されます。以下はその一例です。
from multiprocessing import Process
def print_numbers():
for i in range(10):
print(i)
# プロセスの作成と開始
process = Process(target=print_numbers)
process.start()
# 主プロセスでの処理
print("This is the main process.")
# プロセスが終了するのを待つ
process.join()
`multiprocessing`を使うと、実際に複数のCPUコアで作業が行われます。
モジュールインポートの影響
Pythonの並行・並列処理においては、モジュールインポートが非常に重要です。特に`threading`や`asyncio`、`multiprocessing`などのモジュールが関与する場合、インポートの仕方によっては期待した動作をしない可能性があります。
注意点と解決策
モジュールが複数回インポートされると、その中で定義されている関数や変数が重複してしまう可能性があります。この問題を解決する一つの方法は、モジュールの中で`if __name__ == “__main__”:`を使用することです。
# main_module.py
import some_module # some_moduleが重い処理を含む場合
if __name__ == "__main__":
some_module.heavy_function()
このようにすると、モジュールが直接実行された場合だけ`heavy_function`が呼び出され、インポートされた場合は呼び出されません。
応用例1: Webスクレイピング
並行処理を使ってWebスクレイピングを高速化する例です。
import threading
import requests
def fetch_url(url):
res = requests.get(url)
print(f"Content length of {url}: {len(res.text)}")
# 複数のURLに対するスレッドを作成
threads = []
for url in ["https://www.google.com", "https://www.yahoo.com", "https://www.bing.com"]:
thread = threading.Thread(target=fetch_url, args=(url,))
thread.start()
threads.append(thread)
# 全スレッドが終了するのを待つ
for thread in threads:
thread.join()
この応用例では、複数のURLから同時にデータを取得しています。
応用例2: 画像処理
`multiprocessing`を使って画像処理を高速化する例です。
from multiprocessing import Pool
from PIL import Image
import os
def process_image(image_path):
image = Image.open(image_path)
# 画像処理(ここではリサイズをしています)
image = image.resize((100, 100))
image.save(f"resized_{os.path.basename(image_path)}")
# 画像のリスト
image_paths = ["image1.jpg", "image2.jpg", "image3.jpg"]
# プロセスプールを作成
with Pool() as pool:
pool.map(process_image, image_paths)
この応用例では、複数の画像を並列にリサイズしています。
まとめ
Pythonにおける並行・並列処理とモジュールインポートは、より効率的なプログラムを作成するために不可欠です。この記事を参考に、自分のプロジェクトでも並行・並列処理を効果的に活用してください。
コメント