Python コンディションの使い方

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

ふと気づけば蝉の鳴き声が気にならなくなりました。

というよりセミが鳴いていません。

今年羽化したセミも短い寿命を終えて、次の子孫をたくさん残したのでしょうか?

といってもまだツクツクボウシの鳴き声が聞こえてきますが、クマゼミやアブラゼミほどうるさくはないので、そんなに気にはなりません。

個人的には、夕暮れ時に聞こえてくるヒグラシの鳴き声が一番好きなんです。

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

昨日の復習

昨日は、イベントについて学習しました。

イベントは、一つのスレッドを処理している間は、他のスレッドの処理を待たせておいて、最初のスレッドの処理が終わったら、処理を開始するという使い方ができるものでした。

最初に動作するスレッドでログを取得して、残りのスレッドで取得したログ解析するような使い方ができました。

イベントについては、昨日の記事をごらんください。

今日は、コンディションについて学習します。

condition

conditionは、イベントとロックを組み合わせたような使い方ができます。

イベントは、一つのスレッドの処理が終わるのを待ってから複数のスレッドを並列処理しましたが、これにロックを組み合わせて、一つのスレッドの処理が終わってから残り2つにロックをかけて順番に処理するという感じのことができます。

ロックだけで順番に処理できるんじゃない?

という疑問はおいといて、コードを書いてみましょう。

import logging
import threading
import time

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

def thread1(condition):
    with condition:
        condition.wait()
        logging.debug('start1')
        time.sleep(2)
        logging.debug('end1')

def thread2(condition):
    with condition:
        condition.wait()
        logging.debug('start2')
        time.sleep(2)
        logging.debug('end2')

def thread3(condition):
    with condition:
        logging.debug('start3')
        time.sleep(2)
        logging.debug('end3')
        condition.notifyAll()

if __name__ == '__main__':
    condition = threading.Condition()
    t1 = threading.Thread(target=thread1, args=(condition, ))
    t2 = threading.Thread(target=thread2, args=(condition, ))
    t3 = threading.Thread(target=thread3, args=(condition, ))
    t1.start()
    t2.start()
    t3.start()

昨日のイベントのコードで、eventconditionに変更して、thread1thread2thread3は、withステートメントを使った関数にしています。

31行目では、threading.Condition()conditionオブジェクトを作成して、32行目から34行目でそれぞれのスレッドにターゲットとオブジェクトを代入しています。

関数thread3では、イベントのときはset()だったものをnotifyAll()に変更して、withステートメントを使っています。

thread1thread2withステートメントを使っていますが、こちらは、eventconditionに変わっただけでwait()はそのままです。

実行結果

Thread-3: start3 #←ここで2秒ポーズ
Thread-3: end3
Thread-1: start1 #←ここで2秒ポーズ
Thread-1: end1
Thread-2: start2 #←ここで2秒ポーズ
Thread-2: end2

上記のように、スレッドが、312の順番に処理されて終了します。

書いても書かなくても結果は変わりませんが、最後の行に、3つのスレッドの完了を待つためのjoin()を明示的な意味合いで記述したほうがいいかもしれません。

復習は大事

毎回言ってることですが、復習はホント大切です。

loggingで文字を出力していましたが、毎回毎回コードが長いので、スレッドの名前をprint出力しようと思ってコードを変えようとしたところ、どんなに書くんだったかな?と悩んでしまいました。

答えは、print(threading.currentThread().getName(), 'start1')になるのですが、やはりコードが長くなるよな〜と思って、loggingのままにしておきました。

たまにこうして、過去に学習したコードで書くとどうなるんだろうと復習するのも大切ですので、あえて長くなるコードを考えてみてもいいかもしれませんね。

Vim

酒井さんの講座を受講していると、たまに「ん??」という操作が目に付きます。

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

これは、講座の中でも少し触れられているプログラマー御用達のテキストエディタ【Vim】の操作によるものです。

マウスを使わず、キーボードだけで操作をするエディタということはわかっていたのですが、まだ使う必要がないかなと思っていました。

しかし、最近エクセルでマウスを使わず作業時間を短縮する【脱マウス】を読んでから、極力マウスに頼らず操作できるようにないたいと思い、いろいろと調べているとブラウザーをキーボードだけで操作できる【Vimium】というvimの機能拡張があったので、使ってみたんです。

そしたら、めっちゃ便利でこれなら、Pycharmでもvimのプラグインを使ったほうがめっちゃ作業スピードが上がるんじゃない?と思って入れてみたんです。

最初は、わけがわからないまま、カーソルがあっち行ったりこっち行ったり、コードが消えたりしてやっぱだめ!ってことで一度外したんですよね。

でも今回、酒井さんのレクチャーでeventconditionに置換していたのがかっこよくて、改めて「Vim使いて〜!」となったわけです。

そこで、ネットで再検索すると、Vimはサーバーを扱うプログラマーとして必須のスキルであるという記事や一度踏み入れたら後戻りはできないエディタだという記事、導入にかかる学習コストが半端ないなんて記事がありました。

とにかく、プログラマーのスキルとしては必須で、最初は使いづらくても、使い続ければきっと手放せないスキルになると思い、Vimを使い始めました。

Python学習365日チャレンジが終わる頃には、PythonマスターだけでなくVimマスターになれるよう学習を継続していこうと思います。

それでは明日も、Good Python!