MacOS用のMenuBarアプリを作成する



導入
Pythonは多くのことを構築するために素晴らしいですが、MacOSアプリは確かにそれらの1つではありません.私はそれが可能な場合は、メニューバーのアプリをMacOSのPythonを使用してビルドすることが可能だと思った.私は、それが可能であるだけではないとわかりました-それは「途方もなく複雑でない」です.
このチュートリアルでは、すべてのPythonを使用して株価のリアルタイムMacOSアプリを構築する予定です.

依存関係をインストールすることから始めましょう.
rumps
requests
py2app

うわさ
RumpsはPyObRCアプリを生成します(特にメニューバーアプリ)シンプルなPythonコードから.Rumpsモジュールをテストするには、次のコードを実行します
import rumps
def hello(sender):
    print(f"Hello from {sender.title}")

app = rumps.App("Hello World")
app.menu = [rumps.MenuItem("Weird Menu Item",callback=hello)]
app.run()
The hello() 関数は、メニュー項目がクリックされたときに実行される.
>>> Hello from Weird Menu Item
より多くのメニュー項目を追加するには、我々はアプリに多くの要素を追加することができます.メニュー一覧.引数送付者はコールバックを設定したmenuitemを表します.
同じ結果を得るためのクリーンな方法はrumps.clicked デコレータ
@rumps.clicked("Weird Menu Item")
@rumps.clicked("Saner Menu Item")
def hello(sender):
    print(f"Hello from {sender.title}")

app = rumps.App("Hello World")
app.run()
我々は、チュートリアルの残りのためのデコレータのアプローチに固執する.

株価データ
株式の引用を取得する多くのソースがあります.FinnHubのAPIを使用します.
GET https://finnhub.io/api/v1/quote?symbol=AAPL&token=YOUR_API_KEY
サンプルレスポンス:
{
   "c":119.49,
   "h":119.6717,
   "l":117.87,
   "o":119.44,
   "pc":119.21,
   "t":1605436627
}
に登録することができますhttps://finnhub.io/register フリーAPIキー.この制限書を書くときに60リクエスト/分です.

StockAppのビルド
rumpsのサブクラスとして“stockapp”という名前のクラスを開始します.アプリケーションクラス、およびいくつかのメニュー項目をrumpsを使用して追加します.クリックしたデコレータ
import rumps
class StockApp(rumps.App):
    def __init__(self):
        super(StockApp, self).__init__(name="Stock")

    @rumps.clicked("MSFT")
    @rumps.clicked("AAPL")
    def getStock(self, sender):
        self.title = f"{sender.title}"

if __name__ == '__main__':
    StockApp().run()
今ではFinnHub APIとStockAppを統合する時間です.このようにgetstock ()を微調整しましょう.
import requests
import rumps

class StockApp(rumps.App):
    def __init__(self):
        super(StockApp, self).__init__(name="Stock")

    @rumps.clicked("MSFT")
    @rumps.clicked("AAPL")
    def getStock(self, sender):
        response = requests.get(f"https://finnhub.io/api/v1/quote?symbol={sender.title}&token=YOUR_API_KEY")

        stock_data = response.json()['c']
        self.title = f"{sender.title}:{stock_data}"

if __name__ == '__main__':
    StockApp().run()

The getStock() メニューからストックシンボルを選択するとタイトルが更新されます.
しかし、我々はクリックイベントで価格を取得したくない.我々は継続的に選択された株式の価格を更新する機能が必要です.
このループスをするにはTimer クラスを使用すると、rumps.timer() 関数のタイマーを設定します.
@rumps.timer(1)
def do_something(self, sender):
   # this function is executed every 1 second
起動時に、デフォルトのメニュー項目を設定できます.タイマーの装飾機能は、現在選択されているメニュー項目の価格を更新し続けるが、このオプションをクリックしてイベントを変更することができます.
@rumps.clicked("AAPL")
@rumps.clicked("MSFT")
def changeStock(self, sender):
   self.stock = sender.title

@rumps.timer(5)
def updateStockPrice(self, sender):
   # fetch stock quote and update title
これを複雑にしないようにアプリケーションがネットワーク要求を送信されるため、アプリケーションのUIは、要求がプロセス中に実行し続けるので、異なるスレッド上でAPI要求を処理する必要があります.
import threading

@rumps.timer(5)
def updateStockPrice(self, sender):
   thread = threading.Thread(target=self.getStock)
   thread.start()

def getStock(self):
    # code to send API request 

すべてをまとめる
それが完全な実装をどのように見るか、ここにあります.我々は、より多くのキャッチーのタイトルを作ったアイコンを追加して、ユーザー入力のための機能を追加しました.
import threading
import requests
import rumps

class StockApp(rumps.App):
    def __init__(self):
        super(StockApp, self).__init__(name="Stock")

        self.stock = "AAPL"
        self.icon = "icon.png"
        self.API_KEY = "YOUR_API_KEY"

    @rumps.clicked("Search...")
    @rumps.clicked("MSFT")
    @rumps.clicked("TSLA")
    @rumps.clicked("NFLX")
    @rumps.clicked("FB")
    @rumps.clicked("AAPL")
    def changeStock(self, sender):
        if sender.title!="Search...":
            self.title = f" 🔍 {sender.title}"
            self.stock = sender.title
        else:

            # Launches a rumps window for user input
            window = rumps.Window(f"Current: {self.stock}","Search another stock")
            window.icon = self.icon
            response = window.run()
            self.stock = response.text

    @rumps.timer(5)
    def updateStockPrice(self, sender):
        thread = threading.Thread(target=self.getStock)
        thread.start()

    def getStock(self):
        response = requests.get(f"https://finnhub.io/api/v1/quote?symbol={self.stock}&token={self.API_KEY}")

        if response.status_code!=200:
            self.title = "API Error."
            return

        stock_data = response.json()

        current_price = stock_data['c']
        previous_close = stock_data['pc']
        change = current_price-previous_close

        try:
            changePercentage = abs(round(100*(change/previous_close), 2))

            if change<0:
                marker = "🔻"
            else:
                marker = "🔺"

            self.title = f" {self.stock}: {str(response.json()['c'])} {marker}{changePercentage}%"

        # Finnhub returns 0 for non-existent symbols
        except ZeroDivisionError:
            self.title = "Invalid symbol, set to AAPL"
            self.stock = "AAPL"

if __name__ == '__main__':
    StockApp().run()
アプリケーションを実行するには、同じディレクトリ内の“アイコン. png”ファイルを持っている必要があります.下のリンクからダウンロードすることができます.また、あなたのFinnHub APIキーを割り当てることを忘れないでくださいself.API_KEY .
ダウンロード.PNG
ダウンロード.東大CNS
それを変換する.アプリ
今ではアプリは準備ができて、我々はちょうど忍び寄るMacOSアプリを生成する必要があります.これを行うにはpy 2 appを使うことができます.
セットアップをする必要があります.同じディレクトリのPyファイル.それ以外にも、あなたのアプリケーションのアイコンを追加することができます.MacOSアプリのアイコンにファイルタイプがあります.東大CNS
StockApp
  |__ app.py
  |__ setup.py
  |__ icon.png
  |__ icon.icns
設定.Pyファイル:
from setuptools import setup

APP = ['app.py']
DATA_FILES = ['icon.png']
OPTIONS = {
    'argv_emulation': True,
    'iconfile': 'icon.icns',
    'plist': {
        'CFBundleShortVersionString': '1.0.0',
        'LSUIElement': True,
    },
    'packages': ['rumps','requests']
}

setup(
    app=APP,
    name='Stock',
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'], install_requires=['rumps','requests']
)

最後にセットアップを実行します.
python setup.py py2app
あなたは新しく作成されたdist フォルダ.アプリを開き、アクションでそれを参照してください!
あなたが実行時にエラーを取得している場合は、トレースバックを介して行くことができるので、ターミナル経由でアプリケーションを起動します.
open Stock.App/Contents/MacOS/Stock

結論
このように簡単なメニューバーのアプリを作成するのは簡単だと見た.簡単にPython関数をトリガーする力を与えるので、たくさんのことがこの上に構築できます.私たちはmusic controller , サーバーのモニタは、プログラムが実行されている場合は、ストップウォッチ、CPUメートル、フライトの位置トラッカー、インターネットの速度テスト、ちょうどいくつかの名前を確認します.

賛辞:
Rumps on Github
py2app documentation
Icon by Freepik