PythonアプリをWindowsのタスクトレイに常駐させる方法[pystrayの活用 常駐アプリ化]

今回は、Windowsのタスクトレイにアプリを常駐させる方法について紹介します。
あまり活躍の場はないかもしれませんが、常駐アプリを作りたくてやってみましたので紹介します。

ライブラリのインストール

まずはいつも通りライブラリのインストールからです。
今回は、pystrayというライブラリをインストールします。

インストールにはコマンドプロンプトを開いて以下の通り入力し実行します。

pip install pystray

実行結果は以下の通りです。

プログラムと実行結果

ではプログラム全体です。

import threading
from pystray import Icon,Menu,MenuItem
from PIL import Image

def tasktray_create():
    try:
        global icon
        item=[]
        options_map = {'Test': lambda: tasktray_test(),'Quit': lambda: tasktray_abort()}
 
        for option,callback in options_map.items():
            item.append( MenuItem(option,callback,default=True if option == 'Show' else False ) )
            
        menu = Menu(*item)

        image = Image.open("app.ico")
        icon = Icon("name",image,"My System Tray Icon", menu)
        icon.run()
    finally:
        tasktray_abort()

def tasktray_test():
    print("TaskTray Test")
    
def tasktray_abort():
    global icon
    if icon != 0:
        icon.stop()

def main():
    #threading.Thread(target=tasktray_create).start()
    print("Start TaskTray")
    tasktray_create()
    print("Quit TaskTray")

if __name__ == '__main__':
    main()

実行結果は以下です。
Windowsのタスクトレイ内に、設定したアイコンが表示されています。
また、アイコンを右クリックすれば、設定したメニューが表示されます。
メニューは、TestとQuitの2つで、Testをクリックすれば”TaskTray Test”を出力
Quiteをクリックすれば、アプリが終了するように実装してあります。

続いてはプログラムの解説ですが、解説は次ページにて記載します。

プログラム解説

早速ですが、タスクトレイの作成部分です。
以下が作成したする処理となります。

def tasktray_create():
    try:
        global icon
        item=[]
        options_map = {'Test': lambda: tasktray_test(),'Quit': lambda: tasktray_abort()}
 
        for option,callback in options_map.items():
            item.append( MenuItem(option,callback,default=True if option == 'Show' else False ) )
            
        menu = Menu(*item)

        image = Image.open("app.ico")
        icon = Icon("name",image,"My System Tray Icon", menu)
        icon.run()
    finally:
        tasktray_abort()

処理の流れとしては、以下のような流れとなります。

  1. メニューに表示するアイテムの生成
  2. メニュー インスタンスの生成
  3. アイコンイメージのインスタンス生成
  4. アイコン設定
  5. 起動

メニューに表示するアイテムの生成

まずは、メニューに登録するデータを設定します。
以下がそれに該当します。
Pythonの辞書型で、表示するテキストをキーに コールバック関数を紐づけた形でデータを登録しています。
今回の場合、Testにtasktray_test()というコールバックをQuitにtasktray_abort()というコールバックを登録しています。

options_map = {'Test': lambda: tasktray_test(),'Quit': lambda: tasktray_abort()}

labmdaというのが、コールバック関数の前にありますが、これは引数として関数を指定する場合のおまじないのようなものです。何も考えずにつけておけばいいと思います。
ちなみに、これがないと正しく関数が呼ばれないようなので注意してください。
あとこのlabmdaですが、登録の際にも関数が呼ばれてしまうこともあるので注意してください。
※今回の場合、tasktray_abortの方がなぜか呼ばれてしまいます。。
ちょっと余裕があるときに調査してみます。

メニュー インスタンスの生成

続いてMenuに登録するようのインスタンスの生成です。
以下が、その処理部分となります。
itemという箱を生成して、そこにMenuItemとして1で生成したデータをセットしています。
最後に、MenuというAPIを呼び出し今生成したitemを登録しています。

        for option,callback in options_map.items():
            item.append( MenuItem(option,callback,default=True if option == 'Show' else False ) )
            
        menu = Menu(*item)

ここでワンポイントですが、第3引数に設定している”default=True if option == ‘Show’ else False”という部分ですが、これはこういう風に記載するものだとおもってください。
これを記載しておかないと最後のiconを起動する際にエラーで落ちます。
私はこれが最初よく分からなくてはまりました。。。

アイコンイメージのインスタンス生成

続いて、アイコンイメージのインスタンス生成です。

これは、あらかじめ用意したアイコンを読み出ししています。
今回は、本プログラムと同階層にアイコンを用意してそのフォルダにてアプリを実行しているので、パスは記載していませんが、実際使用する場合にはパスありでアイコンを指定した方がよいと思います。

        image = Image.open("app.ico")

アイコン設定

次は、Iconインスタンスに、2と3で生成したイメージとメニューを設定していきます。
イメージは”name”、メニューは”My System Tray Icon”に設定しています。
この文字はこの通りに設定してください。
※これを違う文字にするとそんなオプション知らん!!と怒られます。

icon = Icon("name",image,"My System Tray Icon", menu)

アイコン起動

最後に設定したアイコンを起動すれば、タスクトレイにアイコンが表示されます。

icon.run()

終了する場合は、以下です。

icon.stop()

アプリを落とす場合は、終了させてから落とすようにしてください。

まとめ

今回はタスクトレイに常駐する方法について記載しましたがいかがだったでしょうか?
結構簡単に常駐アプリを作成できるんだなと私はおもいました。
色々とライブラリが提供されているPythonならではですね!!

ちなみにですが、このタスクトレイ常駐ですが、アイコンを起動するとそこで待ち状態に入ってしまって処理が返ってこなくなりますので、実際に使用される際はマルチスレッド化して処理スレッドとは別のスレッドで本処理をすることをおすすめします。

マルチスレッド化する方法が知りたい方は、以下に方法を記載していますのでこちらもみてみてください。

最後に、Pythonの基礎を学びたい方は以下がおすすめです。私も持っていてたまに眺めて勉強していますものですのでぜひ購入して学習してみてください。

にいやん

出身 : 関西 居住区 : 関西 職業 : 組み込み機器エンジニア (エンジニア歴13年) 年齢 : 38歳(2022年11月現在) 最近 業務の効率化で噂もありPython言語に興味を持ち勉強しています。 そこで学んだことを記事にして皆さんとシェアさせていただければと思いブログをはじめました!! 興味ある記事があれば皆さん見ていってください!!