错误处理

IztroError 的 code 分类、触发条件、消息格式与处理模式。

所有收外部输入的入口在入参非法时抛 IztroError。日期格式、日期存在性、 年份范围、时辰索引在核心层前置校验;性别、语言、标识、配置这些字符串取值在绑定层校验。

from x_iztro import IztroError

IztroError 继承自 ValueError,因此既有的 except ValueError 照样接得住, 不必为升级改代码。

code

异常消息面向人,会随版本调整措辞;要在程序里分支请用 .code

code含义典型触发
invalid_date日期非法格式错、日期不存在、超出 1583–9999
invalid_time_index时辰索引越界不在 0–12
invalid_argument其余入参或配置非法性别、语言、星耀标识、宫名、自定义表
internal库内部缺陷应视为 bug 上报

这四个取值与 Rust 的 IztroError::code()、Go 的 iztro.Error.Code 是同一套, 跨语言分支逻辑可以照抄。

from x_iztro import Astro, IztroError

for args in [("2000-2-30", 2, "female"), ("2000-8-16", 13, "female"), ("2000-8-16", 2, "x")]:
    try:
        Astro().by_solar(*args)
    except IztroError as e:
        print(e.code, "|", e)

输出

invalid_date | invalid solar date '2000-2-30': day is out of range for that month
invalid_time_index | time_index must be 0-12, got 13
invalid_argument | invalid gender 'x': expected 'male' or 'female'

不会抛出 PanicException

库内部缺陷导致的 panic 在绑定层被兜住,转成 codeinternalIztroError, 不会漏出 except Exception 捕获不到的 pyo3_runtime.PanicException


日期相关

情形消息
格式不是 YYYY-M-D"2000/8/16"expected 'YYYY-M-D'
年、月、日不是数字"abc-8-16"year is not a number
月份越界"2000-13-1"month must be within 1-12
该月没有这一天"2000-2-30"day is out of range for that month
年份超出支持范围"1500-1-1"year must be within 1583-9999

农历专有(只有 by_lunar 与两个 *_by_lunar_date 查询会碰到):

情形消息
该农历年没有这个月表内缺月month does not exist in that lunar year
该农历月没有这一天"2000-7-30"(七月是小月)day is out of range for that lunar month

农历消息的前缀是 invalid lunar date '<原串>': ,公历是 invalid solar date '<原串>': , 从消息就能看出走的是哪个入口。

示例

from x_iztro import Astro

for date in ["2000-13-1", "2000-2-30", "1500-1-1"]:
    try:
        Astro().by_solar(date, 2, "female")
    except IztroError as e:
        print(e)

输出

invalid solar date '2000-13-1': month must be within 1-12
invalid solar date '2000-2-30': day is out of range for that month
invalid solar date '1500-1-1': year must be within 1583-9999

消息里带上了原始输入,便于在批量处理时定位是哪一条数据出的问题。

边界与陷阱


时辰索引

触发条件 时辰索引不在 0–12。

示例

try:
    Astro().by_solar("2000-8-16", 13, "female")
except IztroError as e:
    print(e)

输出

time_index must be 0-12, got 13

边界与陷阱

13 个而不是 12 个

子时跨午夜,拆成早子时(索引 0)与晚子时(索引 12),因此合法值有 13 个。 从小时数换算用 utils.time_to_index, 它保证结果落在合法范围。


性别与语言

code 均为 invalid_argument

参数合法值消息
gender"male" / "female"invalid gender 'x': expected 'male' or 'female'
language六个语言代码invalid language 'xx': expected one of zh-CN, zh-TW, en-US, ja-JP, ko-KR, vi-VN

语言代码大小写不敏感,"zh-cn""zh-CN" 都接受。 用 Gender / Language 枚举传参可以在写错的当场被 IDE 挡下。


标识相关

工具函数与安星函数收的是语言无关标识,未知标识会报错:

from x_iztro import utils

try:
    utils.get_brightness("nosuchstar", 0)
except IztroError as e:
    print(e.code, "|", e)

输出

invalid_argument | unknown star key 'nosuchstar'

传译名会报错

这些函数只认标识不认译名。传 "紫微" 会得到 unknown star key '紫微'——先用 i18n.key_of 换算。

星盘上的查询方法chart.palacechart.starpalace.has)是另一套规则: 它们同时接受标识与当前语言的译名,且查不到时静默返回 None / False 而不报错。 详见星盘对象


配置相关

ChartConfig 的六个开关与两张自定义表都在排盘时校验,code 均为 invalid_argument

情形消息
开关取值未知invalid yearDivide 'nope': expected 'normal' or 'exact'
四化表的天干标识未知invalid mutagens key 'nope': unknown heavenly stem
某个天干的四化不是四项invalid mutagens for 'jiaHeavenly': expected 4 stars (lu, quan, ke, ji), got 1
某颗星的亮度表不是十二项invalid brightness for 'ziweiMaj': expected 12 entries, got 1

长度是严格校验:四化必须正好四项、亮度必须正好十二项,多一项少一项都报错。 自定义表只收标识不收译名。


处理模式

批量处理时跳过坏数据

rows = [
    {"date": "2000-8-16", "ti": 2, "gender": "female"},
    {"date": "2000-2-30", "ti": 2, "gender": "female"},
    {"date": "1990-3-3", "ti": 13, "gender": "male"},
]

charts, failed = [], []
astro = Astro()

for row in rows:
    try:
        charts.append(astro.by_solar(row["date"], row["ti"], row["gender"]))
    except IztroError as e:
        failed.append((row["date"], e.code))

print(len(charts), failed)

输出

1 [('2000-2-30', 'invalid_date'), ('1990-3-3', 'invalid_time_index')]

转成自己的异常类型

class ChartError(Exception):
    def __init__(self, code: str, message: str):
        super().__init__(message)
        self.code = code


def build(date: str, ti: int, gender: str):
    try:
        return Astro().by_solar(date, ti, gender)
    except IztroError as e:
        raise ChartError(e.code, f"排盘失败: {e}") from e


try:
    build("2000-2-30", 2, "female")
except ChartError as e:
    print(e.code, "|", e)

输出

invalid_date | 排盘失败: invalid solar date '2000-2-30': day is out of range for that month

code 转出去之后,上层就不必再解析文案。

本页目录