FastF1 v2.2.4 Sprint 会话兼容性修复解析:2022 赛季冲刺赛支持的实现细节与演进
【免费下载链接】Fast-F1FastF1 is a python package for accessing and analyzing Formula 1 results, schedules, timing data and telemetry项目地址: https://gitcode.com/GitHub_Trending/fa/Fast-F1
本篇文章以 FastF1 仓库 v2.2.4 变更日志 为核心,深入剖析该版本针对 2022 赛季 Sprint(冲刺赛)会话所做的兼容性修复:包括修复的背景动因、会话分类与赛程解析的底层实现、Ergast 结果加载链路,以及从 2021 到 2024 年 Sprint 格式的完整演进。读完本文,你将理解 FastF1 内部是如何区分“比赛型 Sprint”与“排位型 Sprint”会话的,并能用当前版本的 API 正确加载任意年份(含 2022)的 Sprint 会话数据。
一、版本背景:v2.2.4 修复了什么
在 docs/changelog/v2.2.4.rst 中,v2.2.4 的发布说明仅有一条 Bug Fix:
Bug Fixes:
- compatibility fixes for supporting 'Sprint' sessions for the 2022 season (see also #160)
即:该版本为 2022 赛季的 Sprint 会话提供兼容性修复,并在文档中关联了对应的问题单 #160。从版本时间线看,v2.2.4 是 v2.2.x 修复序列中的一环:其后的 v2.2.5 变更日志 继续修复了 “2022 年 Sprint 会话结果中缺失发车格位置(grid position)、名次(position)与积分(points)” 的问题(#166)。这说明 Sprint 会话在 2022 赛季曾经历一段不稳定的适配期,v2.2.4 正是其中关键的兼容性节点。
要真正理解这次“兼容性修复”做了什么,必须回到 2022 赛季 Sprint 格式本身的技术背景,以及 FastF1 源码中对会话类型的分类逻辑。
二、为什么 2022 赛季的 Sprint 需要“兼容性修复”
Sprint(冲刺赛)是 F1 在 2021 赛季引入的周末赛制,但各赛季对它的称呼与排位属性并不一致,这给数据解析带来了三个层面的命名混乱:
- 2021 赛季:Sprint 在官方数据中被命名为 “Sprint Qualifying”(冲刺排位赛),而它本质上是决定正赛发车格、颁发积分的一场短比赛——即“比赛型”会话;
- 2022 赛季:官方改名为 “Sprint”,属性仍是比赛型会话,但数据源的字段命名、结果接口与此前并不完全兼容;
- 后续赛季:2023 年引入排位型的 “Sprint Shootout”(冲刺赛排位),2024 年起又更名为 “Sprint Qualifying”,此时它才是真正的排位型会话。
这种“同名不同义、同义不同名”的演变,正是 v2.2.4 需要做兼容性修复的根本原因。从源码结构看,FastF1 在 fastf1/core.py#L1188-L1203 中明确按年份维护了两套会话分类元组:
if self.date.year <= 2023: self._RACE_LIKE_SESSIONS = ("Race", "Sprint", "Sprint Qualifying") # in 2021, 'Sprint Qualifying' was used as the name for a race-like # session that set the grid for the main race self._QUALI_LIKE_SESSIONS = ("Qualifying", "Sprint Shootout") else: self._RACE_LIKE_SESSIONS = ("Race", "Sprint") self._QUALI_LIKE_SESSIONS = ("Qualifying", "Sprint Qualifying") # starting from 2024, 'Sprint Qualifying' is the name for the # qualifying-like session that sets the grid for the Sprint # (previously, this was called 'Sprint Shootout')可以看到,代码对“<= 2023”的年份将 “Sprint Qualifying” 视为比赛型会话(这是 2021 年的历史命名),而对 2024 年及以后则把 “Sprint Qualifying” 归入排位型会话。v2.2.4 的兼容性修复,本质上就是让 2022 赛季这种官方名称已变为 “Sprint”、但数据链路尚未完全对齐的会话,能够被正确识别、加载并产出结果。
三、源码级解读:Sprint 会话在 FastF1 中的完整处理链路
3.1 赛程解析:按年份规整会话名称
fastf1/events.py 的赛程构建函数(_get_schedule_from_f1/_get_schedule_from_ergast)负责把各数据源返回的原始会话名规整为统一格式。关键逻辑位于 fastf1/events.py#L496-L519:
elif year in (2021, 2022): if sessions[3]["Name"] == "Sprint Qualifying": # fix for 2021 where Sprint was called Sprint Qualifying sessions[3]["Name"] = "Sprint" if sessions[3]["Name"] == "Sprint": data["EventFormat"].append("sprint") else: data["EventFormat"].append("conventional")这段代码把 2021/2022 两年中第 4 个会话统一规整为 “Sprint”,并将周末格式标记为sprint;在 Ergast 数据源路径(fastf1/events.py#L576-L591)中,2021/2022 的 Sprint 周末会话序列固定为["Practice 1", "Qualifying", "Practice 2", "Sprint", "Race"]。也就是说,无论底层数据源把第三/四个会话叫什么,FastF1 都会在赛程层面对齐为统一的 “Sprint”。
同时,fastf1/events.py#L36-L38 定义了会话名的速记映射,这也是get_session入参的取值依据:
"S": "Sprint", "SQ": "Sprint Qualifying", "SS": "Sprint Shootout",而Event.get_session_name()方法(fastf1/events.py#L925-L931 附近)会把用户传入的 “SQ”“S”“Sprint” 等写法统一归一化——例如对 2021/2022 年,“Sprint Qualifying” 会被归一化为 “Sprint”。这一点在 fastf1/tests/test_events.py#L266-L298 中有完整的分年份测试覆盖:
# 2021/2022 年 assert event.get_session_name('SQ') == 'Sprint' assert event.get_session_name('S') == 'Sprint' assert event.get_session_name('Sprint') == 'Sprint' # 2023 年(Sprint Shootout 格式) assert event.get_session_name('SS') == 'Sprint Shootout' # 2024 年起(Sprint Qualifying 格式) assert event.get_session_name('SQ') == 'Sprint Qualifying'3.2 结果加载:Ergast 只支持“比赛型”Sprint
会话结果加载是 v2.2.4 兼容性修复的核心战场。在 fastf1/core.py#L2588-L2626 中,Session.results的数据源选择逻辑为:
if session_name == "Race": return self._ergast.get_race_results(self.event.year, self.event.RoundNumber) if session_name == "Qualifying": return self._ergast.get_qualifying_results(self.event.year, self.event.RoundNumber) # double condition because of reuse of the "Sprint Qualifying" name # for a race-like session in 2018 and a quali-like session in 2024+ # Ergast only supports the race-like sprint results. if ("Sprint" in session_name and session_name in self._RACE_LIKE_SESSIONS): return self._ergast.get_sprint_results( self.event.year, self.event.RoundNumber ) # TODO: Use Ergast when it supports quali-like sprint results return None这里有一个关键设计:Ergast 数据源只支持比赛型 Sprint 的结果,因此加载逻辑用“会话名包含 Sprint 且属于比赛型会话集合”这个双重条件来判定是否调用get_sprint_results。当传入的是排位型 Sprint(Sprint Shootout / 2024 年后的 Sprint Qualifying)时,Ergast 返回空,代码会回退为“从计时数据计算有限结果”并输出警告(fastf1/core.py#L2616-L2626):
if not response or not response.content: if (("Sprint" in session_name) and (session_name in self._QUALI_LIKE_SESSIONS)): _logger.warning(f"{session_name} is not supported by " f"Ergast! Limited results are calculated from " f"timing data.")与之对应,Ergast 接口层在 fastf1/ergast/interface.py#L1175-L1214 中注册了Races_SprintResultsAPI 类别与SprintResults子类别;fastf1/ergast/structure.py#L341-L345 和 fastf1/ergast/structure.py#L491-L495 则定义了Sprint与SprintResults两个结构体。此外,遗留代码 fastf1/ergast/legacy.py#L19 中仍保留了旧式处理:session in ("Sprint Qualifying", "Sprint")时选择SprintResults——这也印证了历史上 “Sprint Qualifying” 与 “Sprint” 曾被混用为比赛型会话。
四、实战:加载 2022 赛季 Sprint 会话
理解了上述链路后,就可以用当前版本的 FastF1 正确加载 2022 赛季的 Sprint 数据。以 2022 赛季设有 Sprint 的比赛周末为例(当年包括伊莫拉、奥地利、巴西等 Sprint 周末):
import fastf1 # 可选:启用本地缓存,避免重复请求 # fastf1.Cache.enable_cache("path/to/cache") # 方式一:按会话名 sprint = fastf1.get_session(2022, "Emilia Romagna", "Sprint") # 方式二:按速记字母 # sprint = fastf1.get_session(2022, 4, "S") sprint.load() # 加载圈速、遥测、天气、消息等数据 print(sprint.results[["DriverNumber", "Abbreviation", "Position", "Points"]])几点实战说明:
get_session的第二/第三参数支持多种写法:可以是赛季序号(round number)、官方赛事名,也可以是"S"、"Sprint"等会话标识,具体映射见 fastf1/events.py#L36-L38;Session.load()支持按需关闭数据通道,例如sprint.load(telemetry=False, weather=False, messages=False),与 fastf1/tests/test_core.py#L70-L77 中的 Sprint 测试用法一致;- 加载后
session.laps包含 Sprint 全部车手圈速,session.results包含 Sprint 官方结果(Position、Points 等列)。需要注意:v2.2.4 当时只解决了 Sprint 会话的“可用性”,而“发车格、名次、积分缺失”是在后续 v2.2.5 中修复的(#166),因此若你在旧版本上发现结果列不完整,请升级到 v2.2.5 及以上。
从当前仓库看,Sprint 会话的测试已覆盖到 2023 赛季(如 fastf1/tests/test_core.py#L72 中的get_session(2023, 4, "Sprint")),说明这条兼容链路在后续版本中一直被持续验证。
五、演进脉络:从 2021 到 2024 的 Sprint 格式变化
v2.2.4 只是 Sprint 支持长跑中的一站。结合变更日志与源码,可以梳理出 FastF1 对 Sprint 会话支持的完整演进:
| 赛季 | 官方会话命名 | FastF1 会话分类 | 结果数据源 | 相关版本/源码 |
|---|---|---|---|---|
| 2021 | Sprint Qualifying(实为比赛) | 比赛型(Race-like) | Ergast SprintResults | 命名修复见 fastf1/events.py#L497-L499 |
| 2022 | Sprint | 比赛型(Race-like) | Ergast SprintResults | v2.2.4 兼容性修复(#160),结果列修复见 v2.2.5(#166) |
| 2023 | Sprint + Sprint Shootout | Sprint 为比赛型;Shootout 为排位型 | 比赛型走 Ergast,排位型回退计时数据 | fastf1/core.py#L1188-L1195 |
| 2024+ | Sprint + Sprint Qualifying | Sprint 为比赛型;Qualifying 为排位型 | 同上 | 排位型 Sprint 结果仍回退计时数据(见 fastf1/core.py#L2608-L2612 的 TODO) |
可以看出一个关键设计原则:FastF1 始终把 Sprint 当作“比赛型”会话对待(可颁发积分、决定发车格),同时通过“年份 + 会话名”双维度动态归类,适配了不同赛季的命名漂移。而排位型 Sprint 会话(Sprint Shootout / Sprint Qualifying)由于 Ergast 不支持,其有限结果由计时数据计算得出——fastf1/core.py#L2608-L2612 中的 TODO 注释表明,待数据源支持后这条回退路径会被正式接口替换。
六、结语
v2.2.4 的“一行式”变更日志背后,是一次针对 2022 赛季 Sprint 会话的完整兼容性适配:从赛程解析层的名称规整(fastf1/events.py),到会话分类层的年份判定(fastf1/core.py),再到结果加载层对 Ergast 数据源能力的动态判断。今天使用fastf1.get_session(2022, ..., "Sprint")能顺利拿到结果,正是这条链路持续演化的成果。若想进一步追溯,可对比 v2.2.4 与 v2.2.5 两份变更日志,并阅读 test_events.py 与 test_core.py 中针对 Sprint 的分年份测试用例。
【免费下载链接】Fast-F1FastF1 is a python package for accessing and analyzing Formula 1 results, schedules, timing data and telemetry项目地址: https://gitcode.com/GitHub_Trending/fa/Fast-F1
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考