run_everyデコレータ
新しいPythonエディタのαリリースで使える最新の MicroPython (執筆時点では 2.0.0-2021-10-25)ですが、 run_forever
デコレータが使えます。
デコレータとは、関数の前につける修飾で、関数の処理の前後に処理を付け加えるものです。
たとえば次のように使います。
from microbit import display, Image, run_every
small = False
@run_every(s=1)
def heartbeat():
global small
if small:
display.show(Image.HEART_SMALL)
else:
display.show(Image.HEART)
small = not small
大きなハートと小さなハードが1秒おきに切り替わります。
while ループと何が違うか
動きをみていれば、これは s=1 で指定した秒の間隔で関数 beart の呼び出しを繰り返すものと察しがつくでしょう。
繰り返すだけであれば while ループでもできます。
from microbit import display, Image, sleep
small = False
while True:
if small:
display.show(Image.HEART_SMALL)
else:
display.show(Image.HEART)
small = not small
sleep(1000)
では、なぜこんなデコレータが用意されたのでしょうか。
run_everyデコレータは、MakeCodeの「ループ」にあるeveryブロックと同じ働きをします(これはまだ日本語化されてませんね)。なぜかループに分類されていますが、everyブロックが他のループブロックと違っているのは「バックグラウンド」で繰り返すことです。
「バッググラウンド」で実行するとは、メインの処理とは独立に動作することです。つまり、メインの処理とは並行に動かせます。さらには複数のeveryブロックを並行に動かせます。run_everyデコレータは同じことが行えるので、MicroPython でも処理を並行で動かせるようになったのです。
次のもので試してみると、1秒おきに "func_1" が表示され、2秒おきに "func_2" が表示されます。
from microbit import run_every, running_time
@run_every(s=1)
def func_1():
print(running_time(), "func_1")
@run_every(s=2)
def func_2():
print(running_time(), "func_2")
MakeCode の「ずっと」と同じことがMicroPythonでもできる
MakeCode に「ずっと」という無限ループに相当するブロックがあり、MicroPythom では「while True」に例えられるたりしてますが、これも単なる無限ループと異なるのは」バックグラウンド」で実行されることです。
ちょっと調べると「ずっと」内の処理を一回実行するごとに 20ms のスリープが入ることになっているようで、実際に試してもそのようになっていました。なので「ずっと」をMicroPythonで実現するには次のようにすればよいわけです。
@run_every(ms=20)
def 適当な関数名():
何か処理
run_every の引数
run_everyデコレータには以下の引数を指定できます。組み合わせて使うこともできます。
引数名 | 説明 | デフォルト |
---|---|---|
days | 日単位で実行間隔を指定 | 0 |
h | 時単位で実行間隔を指定 | 0 |
min | 分単位で実行間隔を指定 | 0 |
s | 秒単位で実行間隔を指定 | 0 |
ms | ミリ秒単位で実行間隔を指定 | 0 |
ちなみに、なにも指定しないと実行間隔が0になり、バックグラウンドでCPU使いまくりで制御がメイン戻ってこず、何もできなくなります。対処方法としてはMicroPythonファームウェアを再インストールするしかなさそうです。