股市资深大牛用Python写了个股票价格实时MacOS应用程序!实时监控!

导言

虽然Python很适合构建很多东西,但MacOS应用程序肯定不是其中之一。我想知道是否可以使用Python为MacOS构建菜单栏应用程序。我发现这不仅是可能的,而且“非常简单”。

在本教程中,我们将构建一个股票价格实时MacOS应用程序--全部使用Python。

本文需要完整項目源代碼點這裏獲取

让我们从安装依赖项开始。

rumps
requests
py2app

PyObjC

转储从简单的python代码生成PyObjC应用程序(特别是menubar应用程序)。若要测试转储模块,请运行以下代码:

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()

这个hello()函数在单击菜单项时执行。

>>> Hello from Weird Menu Item

要添加更多菜单项,我们只需向app.Menu列表中添加更多元素即可。参数发件人表示设置回调的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(基于auth键,免费使用)。

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

启动一个名为“StockApp”的类,作为Rumps.App类的子类,并使用rops.Click装饰器添加一些菜单项:

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()

现在是将StockApp与FinnHub API集成的时候了。让我们像下面这样调整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()

这个getStock()方法在从菜单中选择股票符号时更新标题。

但是,我们不想通过点击事件获得价格。我们需要一个函数来不断更新所选股票的价格,比如说每隔几秒钟就更新一次。

做这个腮腺炎有一个Timer类,您可以用rumps.timer()若要在函数上设置计时器,请执行以下操作。

@rumps.timer(1)
def do_something(self, sender):
   # this function is executed every 1 second

在启动时,我们可以设置一些默认的菜单项,比如“AAPL”。此选项可以通过单击事件进行更改,而计时器修饰功能将不断更新当前所选菜单项的价格。

@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

不要让这件事复杂化,但是由于应用程序将发送网络请求,我们需要在另一个线程上处理API请求,以便在请求处理过程中应用UI继续运行。

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 

把一切都放在一起

以下是它对完全实现的看法。我们增加了图标,使标题更吸引人,并增加了用户输入功能(使用rops.window)。

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" :mag: {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 = ":small_red_triangle_down:"
            else:
                marker = ":small_red_triangle:"

            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()

要运行该应用程序,您需要在同一个目录中有一个“ic.png”文件。你可以从下面的链接下载它,或者从程序中删除图标。另外,不要忘记将FinnHub API密钥分配给self.API_KEY .

下载icon.png

下载icns

将其转换为.app

现在应用程序已经准备好了,我们只需要生成一个可移植的MacOS应用程序。我们可以使用py2app来完成这个任务。

您需要在同一个目录中有一个setup.py文件。除此之外,您还可以为应用程序添加一个图标。MacOS应用程序图标的文件类型为.icns

StockApp
  |__ app.py
  |__ setup.py
  |__ icon.png
  |__ icon.icns

Setup.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函数。我们可以音乐控制器,一个服务器监视器,看看一个程序是否正在运行,秒表,CPU计时器,飞行位置跟踪器,互联网速度测试,仅举几个例子。

Guess you like

Origin blog.csdn.net/weixin_43881394/article/details/120883105