Help us understand the problem. What is going on with this article?

Pythonの並列・並行処理サンプルコードまとめ

More than 1 year has passed since last update.

Pythonで同時に2つ以上の処理をする方法を紹介します

  • スレッド
  • スレッドプール
  • プロセスプール
  • イベントループ(コルーチン)

スレッド (threading)

スレッドを使えば、複数の関数を同時に動かすことができます。
threading.Thread クラスに target として関数を渡し、start() で開始すると動きます。

import time
import threading


def func1():
    while True:
        print("func1")
        time.sleep(1)


def func2():
    while True:
        print("func2")
        time.sleep(1)


if __name__ == "__main__":
    thread_1 = threading.Thread(target=func1)
    thread_2 = threading.Thread(target=func2)

    thread_1.start()
    thread_2.start()

実行結果

func1
func2
func2
func1
func1
func2
func2
func1

スレッドプール (concurrent.futures)

Python 3.2以降の、concurrent.futures パッケージ を使うとさらに強力です。
その中の ThreadPoolExecutor クラス を使います。

最初に同時に動かす最大数 max_workers を決めるとスレッドを使いまわしてくれるので上で紹介した普通のスレッドよりかしこいです。
Pythonのバージョンが新しいならば、積極的に使っていいと思います。

import time
import concurrent.futures


def func1():
    while True:
        print("func1")
        time.sleep(1)


def func2():
    while True:
        print("func2")
        time.sleep(1)


if __name__ == "__main__":
    executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)
    executor.submit(func1)
    executor.submit(func2)

実行結果

func1
func2
func1
func2
func1
func2
func1
func2

プロセスプール (concurrent.futures)

上に同じく concurrent.futures パッケージ ですが、スレッドプールではなくプロセスプールというのもあります。

スレッドではなくプロセス単位に分けることで、Global Interpreter Lock (GIL) の制約を受けなくなりマルチコアで動かせるようになります。
ただし、その分スレッドよりも規模が大きいプロセスを使うので、他の制約が増えることも。注意!

使い方は簡単で、上で紹介した ThreadPoolExecutorProcessPoolExecutor に変えるだけです。

import time
import concurrent.futures


def func1():
    while True:
        print("func1")
        time.sleep(1)


def func2():
    while True:
        print("func2")
        time.sleep(1)


if __name__ == "__main__":
    executor = concurrent.futures.ProcessPoolExecutor(max_workers=2)
    executor.submit(func1)
    executor.submit(func2)

実行結果

func1
func2
func1
func2
func1
func2
func1
func2

イベントループ(コルーチン)

ひとつのスレッドで複数の処理を動かす方法もあります。そのひとつがイベントループです。
Python3.4以降では asyncio モジュール で実現できます。

マルチスレッドとの違い、どのような場合に使うと良いか…といったお話は Pythonにおける非同期処理: asyncio逆引きリファレンス を読むとわかりやすいです。

通信やファイル入出力といった非同期I/Oあたりにはスレッドを増やすよりも非常に効率的なのですが、概念が難しいのでなれるまで大変です・・。

サンプルコードはスレッドの場合とは結構違います。

待機する処理に time.sleep ではなく asyncio.sleep を使っていますが、これは asyncio.sleep を呼び出して待っている間に他の並列している処理に移動するためです。まさにコルーチンですね。

import asyncio


@asyncio.coroutine
def func1():
    while True:
        print("func1")
        yield from asyncio.sleep(1)


@asyncio.coroutine
def func2():
    while True:
        print("func2")
        yield from asyncio.sleep(1)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    tasks = asyncio.wait([func1(), func2()])
    loop.run_until_complete(tasks)

実行結果

func2
func1
func2
func1
func2
func1
func2
func1
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした