見出し画像

MacのメニューバーアプリをPythonで作る(2024年3月時点)

Macのメニューバーアプリを作ってみたいとずっと思っていました。
メニューバーアプリとはMacデスクトップ上部に表示されている部分で常駐しているようなアプリですね。メインアプリみたいなリッチな機能は必要なくシンプルな機能で十分なシーン向けに使われているアプリが多いイメージです。

メニューバー


でもSwiftなどを覚える必要がありそうで自然と避けてしまっていたのですが、改めて調べてみたところPythonでもサクッと作ることができるライブラリがあることを知りさっそく作ってみました。

正常に動作する環境を構築することに少し手間取りましたが、アプリ自体の作成は本当に非常に簡単でした。
2024年3月時点でMacBook(M2チップ)環境での動作確認が取れた手順を共有したいと思います。

作成アプリ

Awesome Appと書いてあるものが作成するアプリです。いくつかコマンドがありアラートや通知を行うことができます。(詳細は後述)

今回作成するアプリはrumpsパッケージのDocs内にあるメニューバーアプリになります。でもこれが簡単に作れるとなると色んなアイデアに発展できそうで今はワクワクしています。アプリはスタンドアロンで動作しますので、他の人に共有することなども当然可能です。

動作環境構築

結論から言うと2024年3月時点ではPython3.7環境でのみ正常に動作することの確認が取れました。Python3.8以上の環境では後述するエラーに遭遇してしまい解決することができませんでした。
なのでサクッと作ってみたい人はPython3.7環境で試してみることをお勧めします。

必要なPythonパッケージ

以下の2つのパッケージがコアになります。Python3.7環境でpipなどでインストールしてください。

  • rumps: 0.4.0

  • py2app: 0.28.7

Python3.8以上の環境でのエラー

Python3.8以上で私が遭遇したエラーを共有しておきます。今回は解決策を見つけることができませんでしたが、もしかしたらもう少し調べれば解決策はあるのかもしれません。解決できた方がいれば教えてください。

(rumps-sample-py3.8) $ rumps_sample/dist/sample.app/Contents/MacOS/sample
rumps_sample/dist/sample.app/Contents/Resources/__boot__.py:426: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
Traceback (most recent call last):
  File "rumps_sample/dist/sample.app/Contents/Resources/__boot__.py", line 471, in <module>
    _run()
  File "rumps_sample/dist/sample.app/Contents/Resources/__boot__.py", line 394, in _run
    exec(compile(source, path, "exec"), globals(), globals())
  File "rumps_sample/dist/sample.app/Contents/Resources/sample.py", line 1, in <module>
    import rumps
  File "rumps_sample/dist/sample.app/Contents/Resources/lib/python3.8/rumps/__init__.py", line 25, in <module>
    from . import notifications as _notifications
  File "rumps_sample/dist/sample.app/Contents/Resources/lib/python3.8/rumps/notifications.py", line 14, in <module>
    import Foundation
  File "<frozen zipimport>", line 259, in load_module
  File "Foundation/__init__.pyc", line 188, in <module>
  File "Foundation/__init__.pyc", line 12, in _setup
  File "<frozen zipimport>", line 259, in load_module
  File "CoreFoundation/__init__.pyc", line 37, in <module>
  File "CoreFoundation/__init__.pyc", line 12, in _setup
  File "<frozen zipimport>", line 259, in load_module
  File "objc/__init__.pyc", line 6, in <module>
  File "<frozen zipimport>", line 259, in load_module
  File "objc/_objc.pyc", line 13, in <module>
  File "objc/_objc.pyc", line 2, in __load
ModuleNotFoundError: No module named 'imp'
2024-03-14 14:04:55.426 sample[57536:15832038] Launch error
2024-03-14 14:04:55.426 sample[57536:15832038] Launch error
See the py2app website for debugging launch issues

ModuleNotFoundError: No module named 'imp'
というのがエラーの原因ですね。
色々調べましたが、impモジュールはPython3.8以降サポートされていないみたいでした。
このエラーはPython3.7環境では発生せず正常に動作します。

コーディング

環境さえできてしまえばあとはほぼドキュメント通りで問題ありませんでした。

#sample.py

import rumps

rumps.debug_mode(True)

class AwesomeStatusBarApp(rumps.App):
    def __init__(self):
        super(AwesomeStatusBarApp, self).__init__("Awesome App")
        self.menu = ["Preferences", "Silly button", "Say hi"]

    @rumps.clicked("Preferences")
    def prefs(self, _):
        rumps.alert("jk! no preferences available!")

    @rumps.clicked("Silly button")
    def onoff(self, sender):
        sender.state = not sender.state

    @rumps.clicked("Say hi")
    def sayhi(self, _):
        rumps.notification("Awesome title", "amazing subtitle", "hi!!1")


if __name__ == "__main__":
    AwesomeStatusBarApp().run()

sample.pyに上記のコードを貼り、$python sample.pyを実行すれば、メニューバーにアプリが立ち上がります。正常動作することが確認できます。

Preferenceボタンを押すと、アラートポップアップとテキストが表示されます。
Sayhiボタンを押すと、通知バナーからのメッセージが届きます。

通知バナーからのメッセージが届かない場合

Sayhiボタンを押しても通知バナーからのメッセージが届かない場合は、Macの設定からPythonからの通知を許可しているかどうか確認してみてください

スタンドアロン化

先ほどはPythonコマンドから実行しましたが、メニューバーアプリとして独立させて稼働させたいためスタンドアロン化します。これも簡単です。
sample.pyと同じディレクトリにsetup.pyというファイルを作成し、以下の内容を記述してください

# setup.py

from setuptools import setup

APP = ['sample.py']
DATA_FILES = []
OPTIONS = {
    'argv_emulation': True,
    'plist': {
        'LSUIElement': True,
    },
    'packages': ['rumps'],
}

setup(
    app=APP,
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)

setup.pyが作成できたら下記のコマンドでビルドを行います。

python setup.py py2app

Python3.7環境でのビルド中のエラーについて

私が試したPython3.7.17のそのままの環境では唯一このビルド中に以下のエラーが発生します。

ValueError: '/.pyenv/versions/3.7.17/lib/libpython3.7.dylib' does not exist 

libpython3.7.dylibというファイルが見つかりませんというエラーです。でもPython3.7.17環境ではlibpython3.7m.dylibというファイルがあ離、これが同じ役割を持つファイルになるため、このファイルへシンボリックリンクを作成してあげることでエラーが解決できます。

ln -s /path/to/lib/libpython3.7m.dylib /path/to/lib/libpython3.7.dylib

ビルド実行中はたくさんログが流れますが、ログの最後にDone!と表示されたらビルド完了です。

Done!が表示されたらビルド完了

スタンドアロンアプリを起動

ビルドしたアプリはdistディレクションの配下に作成されています。これをダブルクリックすれば起動できます。

dist配下にアプリが作成されています

これでスタンドアロンアプリができたため、Applications配下に移動させてしまいましょう。Safariなどと並べることができるので立派なアプリぽいですね!アイコンなども作っていけばよりかっこいいアプリになっていくことができます。

Applications配下に移動させても問題なく起動できます。

以上でMacのメニューバーアプリをPythonで作ることができました!今回は簡単なアプリでしたが、これを発展させていけばPythonだけでもより快適なMacライフが楽しめそうです!

この記事が気に入ったらサポートをしてみませんか?