Python学習【365日チャレンジ!】207日目のマスターU(@Udemy11)です。
ふと気づけば庭の木の枝から大部分の葉っぱがなくなっているのに気づきました。
よくよくみてみると、たくさんのミノムシの簑がぶら下がっているので、どうやらミノムシが葉っぱを食い散らかしていたみたいです。
以前もみじを植えていたのですが、こちらはカミキリムシにやられて枯れてしまったので、同じように枯れてしまわないよう、駆除しておきました。
といってもぶら下がっている枝を切り落としただけなので、地面からまた這い上がってくるかもしれませんが。。。
害虫予防は重要ですね。
それでは、今日もPython学習をはじめましょう。
昨日の復習
昨日は、デーモンスレッドについて学習しました。
プログラミングにおけるデーモンは悪魔のことではなく、常駐ソフトのことですが、Pythonのdaemonはちょっと意味合いが違いました。
threadをデーモン化することで、デーモン化したthreadが処理を完了するのを待たずにプログラムを終了させることができました。
逆にデーモン化したthreadの終了を待つための関数がjoin
でした。
今日は、生存中!?のスレッドを返すenumerateについて学習します。
forループ
threadはfor
ループを使って複数のthreadを立ち上げることができます。
import logging
import threading
import time
logging.basicConfig(
level=logging.DEBUG, format='%(threadName)s: %(message)s')
def thread():
logging.debug('start')
time.sleep(1)
logging.debug('end')
if __name__ == '__main__':
threads = []
for _ in range(3):
t = threading.Thread(target=thread)
t.start()
threads.append(t)
14行目で空のリストthreads
を定義し、for
ループを使って3つのスレッドをリストに入れて実行します。
実行結果
Thread-1: start
Thread-2: start
Thread-3: start
Thread-1: end
Thread-3: end
Thread-2: end
3行目まで出力されたあと、1秒後に残りの行が出力されます。
17行目にt.setDaemon(True)
を挿入すると、上記実行結果の3行目までの出力でプログラムが終了します。
join
を使って最後までスレッドを実行しようと最後の行にt.join()
を入れて実行すると、実行結果は次のようになります。
実行結果
Thread-1: start
Thread-1: end
Thread-2: start
Thread-2: end
Thread-3: start
Thread-3: end
1行目の出力のあと、1秒後に2行目と3行目が出力されて、1秒後に4行目と5行目、さらに1秒後に6行目が出力されます。
これでは並列処理にはなりませんね。
threadsをループしてjoin
for
ループでデーモン化した複数のスレッドを同時進行するには、スレッドを入れたリストthreads
をfor
ループで回してjoin
すれば並列処理することができます。
if __name__ == '__main__':
threads = []
for i in range(3):
t = threading.Thread(target=thread)
t.setDaemon(True)
t.start()
threads.append(t)
for thread in threads:
thread.join()
ハイライトした20行目と21行目で作成したスレッドをjoin
しています。
このコードを実行すれば、最初の実行結果と同じになります。
enumerate
enumerate
を使えば、リストthreads
を作らなくてもここまでのコードと同じ処理をすることができます。
if __name__ == '__main__':
for i in range(3):
t = threading.Thread(target=thread)
t.setDaemon(True)
t.start()
for thread in threading.enumerate():
if thread is threading.currentThread():
print(thread)
continue
thread.join()
enumerate
を使えば、空のリストを定義して代入する必要がなくなります。
ただ、enumerate
は、生存中(進行中)のスレッドを返すので、自動的に生成されるメインスレッドオブジェクト(MainThread
)も含まれます。
19行目から21行目はthread
がMainThread
だった場合は、thread
を出力して、join
しないというコードなので、「不要なのでは?」なんて思い、抜いて実行してみました。
すると下記のようなエラーが。
カレントスレッドはjoin
できないようですね。
なので、19行目から21行目でMainThread
(カレントスレッド)をjoin
から除外しているわけです。
実行結果
Thread-1: start
Thread-2: start
Thread-3: start
<_MainThread(MainThread, started 4671282624)>
Thread-2: end
Thread-3: end
Thread-1: end
4行目でカレントスレッドが出力されたあと、1秒待って残りの3行が出力されます。
味わい深い
このあたりのレクチャーも、酒井さんの講座ではサラッと解説されています。
ここまで学習している人であれば、カレントスレッドがjoin
できないことは前提条件として理解している体で進むので、理解できないことがあれば、すぐにネットで調べたほうがいいでしょう。
とにかくわからないことは自分で調べて、いろいろと試してみることが重要です。
それでもわからないときは、直接質問することができるので、最終的に解決することができます。
ほんと酒井さんのPython講座は内容が充実しているので、Pythonの基礎からひととおり学習したい人や復習したい人には超おすすめの講座ですので、ぜひUdemyのセール時に受講してみてください。
それでは、明日もGood Python!