pythonでほぼ周期実行(multiprocessing使用)

我流プログラミング。(がりゅうぷろぐらみんぐまる)

セオリーを無視して、作りたい機能を実装するのが好きなので、欲望のままにプログラミングする。良い子は真似してはいけない

今回やること

電子工作をしていると、一定間隔でセンサの値取りたいとか、ボタンが押されたら今の処理を中断(or終了)して、ある処理をする(割り込み)というのがよくあります。RaspberryPiとかで電子工作をしていると、pythonを使うことが多い(らしい)ですが、pythonでそういった処理をしたいときに少し悩んでしまいます(そもそもpythonでやるべきではないかもですが…)。

今回、pythonのmultiprocessingを利用して”周期的にある関数を実行する”関数を作ってみました。コードは以下のようになりました。python2系でも3系でも動くはずです…。

#!/usr/bin/env python
# coding:utf-8

import time
import multiprocessing

# 受け取った関数を周期的に実行
def Periodic_exec(exec_function,interval=1,count=5):
    for x in range(count):
        delay = multiprocessing.Process(target=time.sleep,args=(interval,))
        delay.start()       # delayプロセス開始
        exec_function()
        delay.join()        # delayプロセスの終了まで待つ

# 実行する関数
def function():
    print("do ->\tAction\t<-end")

# メイン
if __name__ == '__main__':
    Periodic_exec(function,interval=2,count=3)

これをperiodic_exec.pyとでも名付けて、pythonで実行すると、2秒毎に以下の文字が3回表示されると思います。

do ->	Action	<-end

startとjoinを用いて、任意の処理(function)をしながら、time.sleep(interval)の実行が終わるまで待つというのがミソです。これで、一定時間毎に処理を行うというのを実現しています。しかし、このコードでは、time.sleep(interval)を実行するまでの時間を考慮されてないので、正確ではありません。それに、実行する関数の処理がinterval秒以上でもズレてしまいます。このことを図に表すと下のようになります。

forやProcessなどの処理で発生した余分な時間に関しては、time.sleepで遅延するのではなく,時刻情報をきちんと見ながら終了させるようにすれば無くせると思われ…。

使い道としては、大体同じ間隔を開けて、処理を実行したいときに使えると思います。しかし、実際のところ、周期実行のモジュールは普通にありますので、機能的にも見た目的にもそちらを使うべきだとも思います。 ←

 

本記事はあくまでも(主に僕の)勉強のためという位置付けです。あまり参考にしない方が良いかもしれませんね(笑)。当ブログでは、今後もこのように、設計が汚くて野蛮な(ものだと僕が思い込んでる)コードを書いていきたいと思います。議論が捗るコードを書けていければ良いですね。

 

余談

実はpythonそんなに好きじゃない…←