PythonでSetIntervalとSetTimeoutと同じようなことがしたい。

はじめに

JavaScriptで作ったタイピングゲームをPythonに移植しようと思いました。JavaScript版では、カウントダウンタイマーをSetIntervalで実装していますが、同等の実装をPythonでどうするか調べてみました。

結論

  • PythonはJavaスレッドモデルをベースにしたthreadingパッケージがある
  • 一定時間後に、関数を呼び出したい場合は、threading.Timer。
  • 定期的に関数を呼び出したい場合は、threading.Threadを継承し、スレッドモデルで実装すればよい。

インターネットを調べていくと、質問が「SetIntervalのような定期実行をしたい」という質問のため、回答が関数を再帰的に呼び出し、スレッドを毎回生成しているコードを見つけました。(Python Equivalent of setInterval()?) これがPythonとして良いのかどうかはわかりませんが、毎回スレッドを生成するのに違和感があったので、もう少し調べたところ、threading.Threadを継承したサンプルを多く見つけました。

SetTimeoutのように、一定時間後に処理を実行する場合は、threading.Timer

threading.Timer(delay, task)で、待機時間を指定します。また、スレッドプログラミングなので、joinも使えます。

 

Pythonで定期的に関数を実行したいのでSetIntervalを調べる

標準ライブラリーでは用意されていないようです。実装するにはthreading.Event(),event.set(),event.wait()の知識が必要なようです。

少し調べていると、PythonのスレッドはJavaのスレッドモデルを参考にしているので、JavaScriptのSetIntervalで定期的に実行するのではなく、スレッドモデルの書きかたで実装すればよいだけでした。

もう少し具体的に言うと、threading.Threadクラスを継承したクラスを作成し、runメソッドを好みに書き換えればよいだけです。Pythonには、スレッド間通信するための便利なEventオブジェクトがあります。これでwaitの管理などをします。

ちなみにJavaはThread.sleep,Thread.join,Thread.interruptのようにEventオブジェクトではなく、Threadもしくはそのインスタンスでwaitなどを管理します。

基本的なコード

 

カウントダウンタイマー

上記ソースコードをベースに、カウントダウンタイマーを作りました。Countdownクラスを初期化するときの引数にcountで残り秒数を設定できるようにしました。

 

一定間隔で関数を呼び出す

厳密ではないですが、ひとまず一定間隔で呼び出せる。

厳密な間隔で呼び出したいとき

runメソッドのwhileループのチェックで、time.time()を導入します。以下をまずはコピペしてprintでいろいろ出力しながら試すのが簡単だと思います。

https://stackoverflow.com/questions/2697039/python-equivalent-of-setinterval/48709380#48709380