LoginSignup
10
9

More than 5 years have passed since last update.

Tornadoをスケジューラとして使ってマルチタスクっぽいのを実現するメモ

Posted at

TL;DR

Tornadoのioloopを使うと非同期タイマもどきが作れるので,手軽にマルチタスクっぽいことが実現出来る.
多分threadingを使うより手軽.

なにがしたいか

一定周期に実行されるタスクを複数平行して走らせたい.

やり方

tornadoのIOLoopクラスを使うと簡単に非同期ループが実現出来ます.
IOLoopはtornadoでプロセスごとに(多分)一つずつ生成されるイベントループで,いい感じに非同期処理をやってくれます.
IOLoopはプロセスにつき一つずつなので,ソース全体で使い回す必要があります.
tornado.ioloop.IOLoop.current()を呼ぶことで,今使うべきIOLoopクラスのインスタンスが帰って来るのでこれを使いましょう.
インスタンスに対してadd_timeout(deadline, callback)で時間と関数を設定してあげると,時刻がdeadlineをすぎた時に,callbackが実行されます.

tornado_loop_test.py
# -*- coding: utf-8 -*-
import time
import tornado.ioloop


def loop1():
    PERIOD = 2
    ioloop = tornado.ioloop.IOLoop.current()
    ioloop.add_timeout(time.time() + PERIOD, loop1)
    print("loop1")
    # 実際の処理はこの辺に書く(その1)


def loop2():
    PERIOD = 0.5
    ioloop = tornado.ioloop.IOLoop.current()
    ioloop.add_timeout(time.time() + PERIOD, loop2)
    print("loop2")
    # 実際の処理はこの辺に書く(その2)

if __name__ == "__main__":
    loop1()
    loop2()
    tornado.ioloop.IOLoop.current().start()

    print("Ooops!")  # ←実行されない

ループを二つ並列に走らせる例です.
loop1は2秒ごと,loop2は0.5秒ごとに実行されるので実行結果は

loop1
loop2
loop2
loop2
loop2
loop1
loop2
loop2
loop2
loop2
(以下略

のようにloop1が1回実行される間に,loop2が4回実行されています.
なお,一度loop1()loop2()を呼ぶだけだと,IOLoopクラスに登録されるだけで実際にループが走り出さないのでtornado.ioloop.IOLoop.current().start()を呼んでループをスタートさせる必要があります.
一度ループがスタートすると,それ以降の処理は実行されないため最後の行のprint("Ooops!") # ←実行されないはコメント通り実行されないようです.

要は,add_timeoutにコールバック関数が登録さえ出来れば良いのでメンバ関数であろうと無かろうと簡単に並列化ができます.
加えてかなりシンプルなソースで並列化が実現できるのでお勧めです.

10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9