プラグインを作る(6)

プラグインのプロセスはいつ終了するのか? これは重要な点です.

プラグインが作成者の意図しない終わり方をすると問題を起こす場合があるからです. その最たるものがファイルへのデータ保存でしょう. ファイルへの書き込みが終わる前にプラグインのプロセスが終了して(させられて)しまうと, 出来上がるファイルの内容は意図していたのとは違ってしまいます.

ninix-ayaのプラグインはその処理を全て完了して終了する以外にエラーやninix-aya本体の終了によって終了します. エラーを起こして終了するのはプラグイン側の責任で処理すべきものなので, ここではninix-ayaが終了した時にどうなるかを説明します. 結論から言うとninix-aya終了の直前に有無を言わせずプラグインのプロセスは終了させられてしまいます. ninix-aya終了後にプロセスが残ってしまうのを嫌ってこの様な実装になっています. atexitを使って終了処理を登録してあっても実行されない点には特に注意して下さい.

しかし, これではファイルにデータを保存してもその処理が最後まで実行される保証がなく, データを失なうリスクがあります. 次の例はそういった状況をわざと起こさせるためのものです.

from ninix.plugin import BasePlugin

class Plugin(BasePlugin):
    def run(self):
        with open(os.path.join(self.directory, 'test.txt'), 'w') as f:
            for x in range(100):
                f.write('line{0}\n'.format(x))
                print 'count:', x
                time.sleep(1) # sec

このプラグインを実行してから100カウントが終わる前にninix-ayaを終了するとtest.txtの中身はどうなるでしょうか?

この問題を解決するためにBasePluginにはプラグイン終了後も保存されるデータを扱うための次の3つのメソッドが追加されました.(plugin standard 2.3以降で使用出来ます.)

self.set_variable(変数名, 変数値)
self.set_variables(変数の入った辞書)
self.get_variable(変数名)

変数は名前と値を持ち, どちらも文字列(str or unicode)(ninix-aya 4.3.7からUnicodeは使用出来なくなります. マルチバイト文字列はUTF-8でエンコードして下さい.)(str or Unicodeですが, BasePluginのメソッドに渡すマルチバイト文字にはUnicodeを使用して下さい. ファイルに保存する際にはUTF-8に変換されます.)です. 変数名には’:’を使用することは出来ません. これはデータを保存するSAVEDATAファイル(後述)で区切り文字として使用するためで, ‘:’が含まれているとエラーになります. 変数値をNoneにするとその変数は保存されなくなりSAVEDATAから消去されます. 存在しない変数をget_variableで取得しようとするとNoneが返されます. Noneと異なり空文字列は正しい値として扱われます.

set_variable(s)メソッド自体は必ず処理されることが保証されているわけではありません(これらのメソッドの処理が完了する前にプラグインが終了する可能性はあります)が, これらのメソッドから戻った時点で(ninix-ayaが異常終了しない限り)データが保存されることが保証されます.(具体的には変数の情報はキューを使ってninix-ayaに送られ, ninix-ayaがキューからデータを取り出して処理するまでset_variable(s)メソッドはブロックします.) 複数の変数を設定する場合にはset_variablesメソッドの方を使うことでまとめて処理することが出来ます. このメソッドが戻った時点で全ての変数が設定されたことが保証されます.(set_variableを複数回呼び出した場合には途中までしかデータが保存されない可能性があります. set_variablesの場合にはall or nothingです.) set_variablesの引数には

{変数名1: 変数値1, 変数名2: 変数値2, ……}

という形で変数を入れた辞書を渡します.

ninix-ayaに送られた変数の情報はninix-ayaの終了時にプラグインのディレクトリのSAVEDATAファイルに保存され, 次回のプラグインの起動時に読み込まれます.(データの保存のタイミングについては今後変更する可能性があります.)

これらのメソッドでは変数の値を全て文字列にして渡す必要があるため値の型の情報は保存することが出来ません. どうしても型情報を残す必要があれば変数名に入れる(例えば’test[int]’)などプラグイン作成者側での工夫が必要になります.(要望があればninix-aya側での対応も考えます.)

「お天気やん」はバージョン0.5から今回説明したメソッドを使って天気予報をする場所の情報を保存するようになっています. メソッドの使い方の参考にしてみて下さい.

最後にもう一点. ninix-aya 4.3.4以降は同じプラグインを複数起動することが出来ないようにしてあります. ですので, plugin standardを2.3以上に設定している限り, 同じプラグインが複数起動してデータの保存で競合するという心配はありません.

次回は常駐型プラグインを取り上げる予定です.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です