股票数据下载总是中断:分批缓存,只补拉未完成部分
股票下载中断后,应核验完成缓存、恢复尝试次数,只请求未完成工作。文件存在不等于成功,它可能是半个响应、旧请求或损坏字节。大名单开始前先规定缓存约定与有限恢复计划,才能避免每次重启重新取得全部股票,也避免跳过只有空文件的失败对象。
本文在新建临时演示目录里实际写文件、重开与续跑,取得函数完全合成,不发网络请求,不读取或删除用户原有缓存,也不证明CoTrading或Vibe已有通用下载器。某股耗尽预算时,最终结果明确部分完成,不以三个成功文件冒充四股全量数据。
拆成稳定请求单元
股票为AAA、BBB、CCC、DDD,两批分别AAA与BBB、CCC与DDD。每个请求写来源、股票、起止日、频率、复权基础和币种。样例需要2026年10月19、20两日的原始USD收盘。批次方便安排工作,真正复用依据仍是单请求完整键,不能只看某批曾经启动过。
键从完整请求确定生成,不只用代码。周线或复权序列不能满足原始日线请求;来源和日期范围也重要,早先窗口成功不证明后来区间取得。一个标识可以关联多个正确缓存,读取时精确匹配,避免为节省下载而把数据含义换掉。
Python hashlib参考说明本例SHA-256请求键与内容摘要。摘要识别字节变化,不证明供应商价格经济上正确,也不能替代金融字段检查。配置序列化采用固定键次序,才能让相同请求生成同一逻辑身份;变化频率或复权基础则生成不同身份。
定义什么缓存可以复用
每项包含数据文件和独立完成标记。标记保留精确请求及已发布数据字节散列。读取要求两文件都在,请求一致、摘要一致、日期符合、收盘为正且有限。缺或不相容条目不复用。合法JSON也可能是一条错误消息,不能因此写成功标记。
metadata = json.loads(marker.read_text(encoding="utf-8"))
content = data.read_bytes()
if metadata["request"] != request:
return None
if metadata["sha256"] != hashlib.sha256(content).hexdigest():
return None
rows = json.loads(content)
完整例还核两日期结构。真实OHLCV增加字段、单位、重复键和覆盖检查,摘要只验证保留字节身份,不验证这些规则。若供应商数据后来更正,要产生新选择版本或重新验证,不让旧成功标记自动为新内容背书。缓存有效与研究当前可用也可能不同,应分别标记。
先发布数据,再发布完成标记
同目录写暂存文件,关闭后重新读回并校验暂存内容;只有合法内容才能替换正式数据,之后再发完成标记。无效内容抛invalid_cache_payload,不产生新标记;无效替换还必须保持已有正确数据及标记不变。os.replace官方说明描述替换及文件系统限制。本例单进程,不宣称数据库事务、多写者安全或断电持久性,跨文件系统等情况另行设计。
两个文件不是一个原子事务。若数据替换后、标记发布前中断,读取器应因缺标记或摘要不符拒绝半发布项,而不是继续复用。保守核验是恢复机制,重命名本身不能覆盖所有故障。成功标记最后写,也不能免除重启后的再次读回检查。
尝试计数在发起合成请求前持久化,中断也消耗预算,避免重启就忘掉。尝试日志与数据成功分开,计数落盘不代表响应可用。如果实际请求失败,应保留原因与剩余预算;若继续需要新预算,应明确作配置决定,不由循环默默重置。
模拟中断并实际续跑
初始AAA取得一次,带有效标记提交。BBB第一次响应只写截断数据,没有标记,模拟批内写入中断,不是真的终止某个联网进程。CCC和DDD尚未完成。这样既能在磁盘看到半文件,也能检查下一次是否会错误把它当成功跳过。
下载完整示例。使用Python 3.12+、标准库与合成输入,运行python R537.py。作者文件为docs/growth/research/round-5/examples/R537.py。
首轮恢复复用AAA,重新取得并提交BBB,CCC尝试两次失败耗尽预算,DDD完成。总模拟请求次数AAA一、BBB二、CCC二、DDD一,BBB包括中断前一次。每请求最多两次,CCC持续失败也不会无限循环。预算按请求键管理,而不是一个股票失败就阻挡其他已可完成任务。
| 股票 | 首次恢复 | 再次恢复 |
|---|---|---|
| AAA | 复用核验缓存 | 继续复用 |
| BBB | 补完成下载 | 复用 |
| CCC | 预算失败 | 仍失败,不再请求 |
| DDD | 下载完成 | 复用 |
再次恢复会重读磁盘计数,三项有效缓存复用,CCC也不新增请求。断言检查状态与调用次数不变。这验证的是持久化文件驱动的恢复,不只是单个函数调用内存变量还没有消失。输出目录可供检查数据、完成标记和次数台账,理解每个状态的来源。
用半文件与损坏内容挑战成功判断
BBB截断文件是首个反例,文件名存在,却没有有效完成标记与结构。只凭存在跳过,会让批次表面完成而数据不可用。应重取或补足原请求,核验后再写标记,不把一个半文件改后缀就叫修复。
另一个损坏探针在新子目录复制有效项,再改内容,确认摘要拒绝。发布探针先向全新缓存提交负收盘,再向已验证缓存提交同一无效替换,分别断言失败不产生新标记,以及原数据与标记字节完全不变。再以周频或复权基础请求AAA,验证不能复用原始日线。频率和基础相近不代表同一数据对象,这是本题与仅讨论限流不同的实际缓存约束。
tempfile参考说明本例创建全新目录的方法。脚本打印真实路径,并保留这些演示文件,不删除已有缓存。每次运行新建隔离位置,无需模型、凭证或数据商账户。它们只是合成演示产物,不能拿文件存在证明曾经取得真实市场历史。
保留失败上限与诚实完成度
三只有效、一只失败,不是完整四股数据集。交付有效清单、预算失败项与请求范围,后续调查原因再决定是否给新预算。重启不能自动清零,恢复程序也不能把最后尝试结束当所有股票完成。这样既有终止条件,也保留可继续的位置。
真实供应商还要区分临时超时、无效证券、权限和不支持区间,按实际限制处理。样例只有一种合成超时,不模拟全部网络与授权情况。一个不可修复配置不应反复占满预算;需要人工修改来源或范围时明确列出,不用相同请求无限重试。
已验证旧项不能被未完成新响应直接覆盖。先暂存与核验,保留来源,明确选定版本。请求意义变了就用不同键,不重新贴标签到旧字节上。若采用并行批次,还需另行处理锁、并发计数与一致发布,本单进程例没有验证这些能力。
交付可重放恢复包
保留请求、批成员、尝试台账、数据、标记、核验结果与未解决项。审阅者从磁盘重开一个复用项和一个被拒半文件,再重放恢复,确认已完成内容不重复请求或写入。日志应能解释一次调用为什么是复用、取得还是预算停止,而不只是总耗时。
两日期有效缓存只证明声明请求及结构,不保证更广历史覆盖;更多字段、来源修订需各自取得与对账。本文为股票下载交付了真实落盘、半写恢复和有限重试,供应商数据真实性与下游策略正确性仍由对应任务验证,不能从缓存命中推导投资结论。
缓存有效与重试状态分别审阅
一股耗尽预算,另一股仍有可复用数据,报告同时保留,不全池中止,也不把失败项改名完成。复用有效条和拒绝超额请求,是两条不同控制成功路径,只有前者提供数据。数据任务整体仍可能部分完成,状态层级要能表达这种组合,而不是一个总绿灯。
请求键定义与缓存格式版本一起保存。以后新增会话约定或改变数字序列化,应先判断旧项还兼容,再复用标记。摘要只描述覆盖字节,不自动说明字节解释已经改变。格式升级若让旧内容需要转换,就另外验证转换与读回,不靠文件名相同推断可直接使用。
运行后可以查看新演示目录,数据、完成标记和次数台账都实际存在。真实服务还需保留期、权限、并发和持久提交设计,应在目标存储环境检验,不由本单进程合成例推导。这个边界也意味着程序没有清理用户已有缓存,演示产物与生产历史始终分开。
缓存修复若接受了新的合法响应,应保留旧失败记录并更新选定版本;重启只恢复进度,不篡改原失败事实。这样同事接手时能看到已完成部分、预算耗尽部分和下一步配置需求,不必从目录文件数量猜下载是否真的结束。
常见问题
看见文件就能跳过股票吗?
不能,要核请求、标记、摘要、结构和必需覆盖。
重启会重置重试次数吗?
这里不会,次数持久化,反复重启不能静默得到无限预算。