行星位置小部件

Hacker News Top 工具

摘要

本文描述了如何使用 Python 和 Astropy 创建一个 Mac 小部件,该小部件可以显示天体的位置,并提供了代码示例和设置说明。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/08/15 15:39

# 行星位置小组件 来源:https://leancrew.com/all-this/2026/08/a-planet-position-widget/ 上一篇文章 (https://leancrew.com/all-this/2026/08/ill-follow-the-sun/) 2026年8月12日 下午12:16 Dr. Drang 在我学会如何使用TerminalWidget (https://leancrew.com/all-this/2026/08/a-two-month-calendar-on-my-desktop/) 创建Mac小组件,以及如何通过Astropy (https://leancrew.com/all-this/2026/08/ill-follow-the-sun/) 确定天体位置之后,我自然而然地将两者结合,创建了一个跟踪行星位置的小组件。 ## 行星位置小组件 我采用行星的古代定义,包括太阳和月亮,但不包括土星之后的任何天体。数字依次是方位角和高度角,精确到最近的度数。其目的是告诉我哪些天体可能可见及其位置。这张特定的截图拍摄于昨晚10点刚过;由于所有天体都在地平线以下,所以没有必要外出观测。 我曾犹豫是否要包含太阳。我们中很少有人需要帮助才能在天空中找到太阳,而且当太阳升起时,除了月亮什么都看不见。但我还是决定将其纳入,部分是为了完整性,部分是因为某些天体的可见性取决于它们与太阳的角距。 让我们从生成小组件文本的代码开始。这是一个名为`planets`的Python脚本: ``python: 1: import astropy.units as u 2: from astropy.time import Time 3: from astropy.coordinates import get_body, AltAz, EarthLocation 4: from subprocess import run 5: 6: def direction(az): 7: '返回表示方位角(以度为单位)的方向字符串。' 8: 9: dirs = 'N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW'.split() 10: i = int(((az + 11.25) % 360) / 22.5) 11: return dirs[i] 12: 13: # 当前UTC时间。 14: ut = Time.now() 15: 16: # 观测地点。 17: home = EarthLocation(lat=41.81433*u.deg, lon=-88.07093*u.deg, height=208*u.m) 18: 19: # 关注的天体。 20: planets = 'Moon Sun Mercury Venus Mars Jupiter Saturn'.split() 21: 22: # 所有天体的当前位置。 23: pos = {} 24: const = {} 25: for p in planets: 26: pos[p] = get_body(p, ut).transform_to(AltAz(obstime=ut, location=home)) 27: const[p] = pos[p].get_constellation() 28: 29: # 组装结果。 30: output = [] 31: for p in planets: 32: output.append(f'{p:>8s}: {pos[p].az.value:3.0f} \ 33: {direction(pos[p].az.value):3s} {pos[p].alt.value:3.0f} {const[p]}') 34: 35: # 通过TerminalWidget输出结果。 36: tw = '/Applications/TerminalWidget.app/Contents/MacOS/TerminalWidget\ 37: --target planets --font Menlo --bg eeeeee --fg 000000 --text -'.split() 38: run(tw, input='\n'.join(output).encode()) 39: 40: # print('\n'.join(output)) `` 这里没有shebang行,因为它的调用方式是由`launchd`决定的,我们稍后会讲到。`planets`导入必要的模块后,第6–11行定义了`direction`函数,该函数接受方位角并返回对应的罗盘方向字符串。我需要这个函数,因为Astropy报告的方位角223°并不会立刻让我联想到“西南”。该函数假设采用16方位罗盘,如下所示: 维基百科上的罗盘玫瑰图 图片来自Wikipedia (https://en.wikipedia.org/wiki/Points_of_the_compass)。 各方向点之间相隔22.5°,这就是第10行除以22.5的原因。第10行的其他部分调整了以下事实:正北从348.75°(-11.25°)开始,方位角在360°时重置,并且列表索引必须是整数。 Astropy可能已经有一个函数实现了`direction`的功能,但我认为自己编写这个函数比搜索文档更简单(也更有趣)。 第14行和第17行定义了观测的时间和地点。`planets`将每半小时运行一次以更新小组件,因此显示的内容最多滞后30分钟。你看到的`home`位置实际上是Morton植物园;我的脚本版本使用的是我家的经纬度。 第20行定义了`planets`列表,第23–27行创建了两个字典`pos`和`const`,分别包含每个行星的`AltAz` (https://docs.astropy.org/en/stable/api/astropy.coordinates.AltAz.html)位置和星座。`get_body`函数 (https://docs.astropy.org/en/stable/api/astropy.coordinates.get_body.html)(第26行)获取位置,`get_constellation`函数 (https://docs.astropy.org/en/stable/api/astropy.coordinates.get_constellation.html)(第27行)利用该位置来确定天体所在的星座。 第30–33行创建`output`行列表,第36–38行使用`subprocess`模块 (https://docs.python.org/3.13/library/subprocess.html#subprocess.run)的`run`函数将输出行发送给TerminalWidget。`tw`列表包含了`TerminalWidget`可执行文件的完整路径及其所有选项。`run`函数的`input`参数是先前定义的`output`,转换为用换行符分隔的单个字符串并编码为字节。 第40行基本上是一个调试行,我将其保留以备将来开发。在编写`planets`时,我注释掉了第36–38行,取消注释了第40行,这样我就能立即在终端中看到结果。 `planets`通过这个launch agent `com.leancrew.planets.plist`,由`launchd`每30分钟运行一次,即每小时的整点和半点: `` xml: 1: <?xml version="1.0" encoding="UTF-8"?> 2: <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3: <plist version="1.0"> 4: <dict> 5: <key>Label</key> 6: <string>com.leancrew.planets</string> 7: <key>ProgramArguments</key> 8: <array> 9: <string>/path/to/python</string> 10: <string>/path/to/planets</string> 11: </array> 12: <key>StartCalendarInterval</key> 13: <array> 14: <dict> 15: <key>Minute</key> 16: <integer>0</integer> 17: </dict> 18: <dict> 19: <key>Minute</key> 20: <integer>30</integer> 21: </dict> 22: </array> 23: </dict> 24: </plist> `` `ProgramArguments`数组中的第一个项目是Python可执行文件的完整路径(这就是`planets`不需要shebang行的原因),第二个项目是`planets`脚本本身的完整路径。`planets`的运行时间安排在`StartCalendarInterval`数组中——每当分钟数为0或30时,脚本就会运行。 在我写下这段话时,一次日食即将发生。在芝加哥地区,这将是一次非常不明显的日食——只有1%的太阳会被遮挡。由于云层遮挡了100%的太阳,我将无法看到任何日食现象。但我的行星小组件或多或少地向我展示,它正在云层之上发生。 **行星小组件显示日食时间附近** 将太阳和月亮的位置四舍五入到最近的度数,精度不足以确定日食,但这算是一个不错的提示。 上一篇文章 (https://leancrew.com/all-this/2026/08/ill-follow-the-sun/)

相似文章

AstraPixels

Product Hunt

AstraPixels 是一个像素艺术太阳系可视化,显示行星的实时当前位置。