Python学習【365日チャレンジ!】219日目のマスターU(@Udemy11)です。
ふと思ったのですが、レジ袋の有料化よりも、ペットボトルのデジポット制度を導入したほうが環境に優しいんじゃないかと思うんです。
子供の頃は、ファンタの1Lとかも瓶で、駄菓子屋に持っていって瓶代金をもらうなんてことをしてお小遣いにしていたものです。
瓶の場合は、洗って再利用されているので、ペットボトルとは少し違いますが、ペットボトルをお金に変えることができればペットボトルを捨てる人なんていなくなるんじゃないかと思いませんか?
ヨーロッパの方では、すでに導入されている地域があるようですが、システムの構築などにコストや時間がかかるんでしょうね。
それでは、今日もPython学習をはじめましょう。
昨日の復習
昨日は、マルチプロセスについて学習しました。
マルチプロセスは、マルチスレッドと同じような使い方なので、thread
をprocess
に変更するだけで使うことができました。
スレッドで学習したLock
、RLock
、Semapore
、Queue
、Event
、Condition
、Barrier
などがthread
と同じように使えます。
daemon
やjoin()
を使ったコードも学習しました。
マルチプロセスの詳細については、昨日の記事をごらんください。
今日は、プールを使って非同期処理をする方法について学習します。
非同期処理とは
まず最初に、「非同期処理とはなんぞや?」ってところでつまづきました。
なので、非同期処理について少し調べてみました。
非同期処理とは
ある関数が呼び出されたとき、戻り値として本来渡したい結果を返すのではなく、一度関数としては終了し(=呼び出し元に戻る)、後で『本来渡したかった値』を返せる状態になったときに、呼び出し元にその値を通知する仕組み
引用元: 非同期処理ってどういうこと?
とりあえず、ボールを投げておいてそのボールが相手から返ってくるまでに、他の人にちがうボールを渡して、最初のボールが返ってきたらそのボールをバットで打つという感じでしょうか。
いつもながら、よくわからない例えになってしまってますが、最終的な処理の終了を待たずに、メインの処理で次の処理ができるということです。
これまで最初のコードの処理が終わってから次のコードの処理をしたり、最初のコードの処理を始めたあと、次のコードを処理するけど、最初のコードの処理の完了を待たずに終了したりする並列処理を学習してきましたが、今回の非同期処理は、最初のコードの処理をはじめてから次のコードの処理も実行して、最初のコードの結果が返ってくるのを待ってなにかの処理をするという感じです。
デーモン化したあとのjoin()
みたいな感じですが、いまいちどうちがうのか理解できていません。
とりあえず、コードを書いていきましょう。
Pool
multiprocess.Pool
というメソッドをつかって非同期処理を実行します。
import logging
import multiprocessing
import time
logging.basicConfig(
level=logging.DEBUG, format='%(processName)s: %(message)s'
)
def worker1(i):
logging.debug('start')
time.sleep(5)
logging.debug('end')
return i
if __name__ == '__main__':
with multiprocessing.Pool(1) as p:
p1 = p.apply_async(worker1, (100, ))
logging.debug('executed')
logging.debug(p1.get())
12行目までは昨日と同じです。
13行目で関数worker1
の返り値をi
にするコードを加えています。
16行目でwith
ステートメントを使ってmultiprocessing.Pool
を開いていますが、引数は1
にしています。
17行目では、非同期処理のターゲット関数をworker1
にして引数に100
を入れた非同期処理オブジェクトp1
を作成しています。
18行目では、executed
を出力していますが、17行目のp1
オブジェクトを作成した際に実行された関数の返り値がメインプロセスに返ってくる前に、executed
が出力されます。
最初の例えで言うところのボールを投げたあとに他の人にボールを渡すというところですね。(よけいわかりづらいわ!ってツッコミはなしで。。。)
最後の行で、関数worker1
からの返り値i(100)
をget()
で取得して出力しています。
実行結果
MainProcess: executed
ForkPoolWorker-1: start #次の行の出力まで5秒まつ
ForkPoolWorker-1: end
MainProcess: 100
2行目までが出力されたあと、5秒経ってから残りの行が出力されます。
ちょっとした違い
昨日学習したマルチプロセスもマルチスレッドの処理と同じような感じでしたが、今回書いたコードと同じ結果を得るには、スレッドを使ってもできますよね。
例題的に書いているコードなのでシンプルになっていますが、複雑な処理をするようになれば、スレッドと違ったプロセスの使い方がわかってくるんだと思います。
まずは基本的な使い方をマスターしましょう。
それでは明日もGood Python!