Python Queueの複雑な使い方

Python学習【365日チャレンジ!】214日目のマスターU(@Udemy11)です。

住んでいるところは結構田舎なのですが、先日なにやらヘリコプターのような音がするので、外をみてみると、なんとびっくり、ドローンで田んぼの消毒をしていました。

稲から1mくらい上空をきれいにまっすぐ飛んでいくので、思わず見入ってしまったのですが、ほんとこんな田舎までテクノロジーが浸透しているのかと感心してしまいました。

3Dマップでプログラミングして飛ばしているのかと思ったのですが、よくよく見ると遠くの方でリモコンを操作している人がいたので、自動化できているわけではなさそうでした。

それにしてもテクノロジーの発展はすごい勢いで進んでるようですね。

それでは、今日もPython学習をはじめましょう。

昨日の復習

昨日は、queueの応用的な使い方ついて学習しました。

時間のかかる処理をjoinを使って待機してtask.doneで終了を確認してスレッドを終了するというやり方をしました。

デバッグを使うと、処理があっち行ったりこっち行ったりするのがわかるので、トライアンドエラーで試してみることが大切でした。

今日は、さらに突っ込んだキュー(queue)のより実践的な使い方を学習します。

3つのスレッドで処理する

時間のかかる処理を3つのスレッドで並列処理をするコードを考えてみましょう

import logging
import queue
import threading

logging.basicConfig(level=logging.DEBUG, format='%(threadName)s: %(message)s')

def thread1(queue):
    logging.debug('start1')
    while True:
        item = queue.get()
        if item is None:
            break
        logging.debug(item)
        queue.task_done()

    logging.debug('very long work')
    logging.debug('end1')

if __name__ == '__main__':
    queue = queue.Queue()
    for i in range(100000):
        queue.put(i)
    ts = []
    for _ in range(3):
        t = threading.Thread(target=thread1, args=(queue, ))
        t.start()
        ts.append(t)
    queue.join()
    logging.debug('tasks are finished')
    for _ in range(len(ts)):
        queue.put(None)

    [t.join() for i in ts]

20行目までは昨日と同じコードです。

21行目で、なんとびっくり10万回queueに値を代入するforループにして、23行目でthreadを入れる空のリストtsを定義しています。

24行目から27行目で、関数thread1を並列処理で実行する3つのthreadを作成して、先程作ったリストtsに追加します。

28行目のjoinqueueが終了するのを待って、30行目、31行目でtsに入っているスレッドの数だけqueueNoneを代入しています。

これでthread1itemNoneが3回代入されてwhileループがbreakして、3つのスレッドが終了します。

33行目はリスト内包表記ですが、覚えていますか?

    [t.join() for i in ts]

リストを外すと次のようなコードになります。

    for i in ts:
        t.join()

リスト内包表記についてはこちらの記事を参考にしてください。

join()は記述不要ですが、明示的に記述するルールにしたがって、3つのt.join()をリスト内包表記にしています。

実行結果

このコードの実行結果は処理に時間がかかるので、動画にしてみました。

3つのthreadで順番に0から99999までが出力されたあと、tasks are finishedが出力されて、3つのスレッドが終了しています。

コードをいじってみることが大切

酒井さんの講座でも解説されていますが、トライ&エラーを繰り返してみることが大切です。

Udemy講師 酒井さん プログラミング Python

講座では、最後のリスト内包表記でスレッドをjoin()していますが、このコードが無くてもプログラムは問題なく終了するとか、14行目のqueue.task_done()の記述がないとqueueが終了しないとか、実際に試してみないとわかりません。

試してみるとコードが理解できてくるので、楽しくなってきます。

そして、楽しくなってくるとコードの理解の速度が速くなります。

いろいろ試して、楽しくPyhtonをマスターしていきましょう!

それでは明日も、Good Python!