尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Scrapy 版本管理与 API 稳定性:A.B.C 语义、弃用策略与源码级实现解读

Scrapy 版本管理与 API 稳定性:A.B.C 语义、弃用策略与源码级实现解读 Scrapy 版本管理与 API 稳定性A.B.C 语义、弃用策略与源码级实现解读【免费下载链接】scrapyScrapy, a fast high-level web crawling scraping framework for Python.项目地址: https://gitcode.com/GitHub_Trending/sc/scrapy本文基于 Scrapy 仓库中的 版本管理文档系统讲解 Scrapy 的版本号构成规则A.B.C 三段式、开发版本的命名约定、API 稳定性承诺以及至少一年的弃用策略。同时结合当前仓库源码版本号加载机制、ScrapyDeprecationWarning警告体系、create_deprecated_class弃用类工厂等与 发布说明帮助你准确判断何时升级 Scrapy、升级前需要检查哪些弃用项以及为什么以单下划线开头的成员不应被依赖。版本号结构A.B.C 三段式Scrapy 的版本号由三个数字组成写作A.B.C每一段的含义如下段名称含义A主版本号major很少变化代表非常重大的改动B发布号release包含大量改动包括新功能也可能包含破坏向后兼容性的变更但官方力求将此类情况降到最低C修复号bugfix仅包含 bug 修复原文档给出的例子是1.1.1是1.1系列的第一个 bugfix 发布版本可直接用于生产环境。非兼容性变更必须写进发布说明一个关键承诺是所有破坏向后兼容性的变更都会在 发布说明release notes 中被明确提及可能需要在升级前给予特别关注。这一点在当前仓库中可以直接验证docs/news.rst 的每个版本条目下都固定设有Backward-incompatible changes、Deprecations、Deprecation removals三个小节。例如最新版本 Scrapy 2.18.0 的条目就明确列出了移除 zope.interface 运行时接口标记、Crawler.stats等属性在爬取开始前的行为从返回None变为抛出RuntimeError等破坏性变更而更旧的版本条目中则能看到 Removed the--output-format/-tcommand line option, deprecated in ... 这类弃用一年后移除的记录——这正是下节弃用策略在实践中的体现。开发版本不遵循三段式开发版development release不使用三段式版本号而是以dev作为后缀发布例如1.3dev。原文档还附有一条重要的历史注记在 Scrapy 0.* 系列中Scrapy 曾使用奇数版本号表示开发版如 0.13 之后的下一个开发版用 0.15 表示。自 Scrapy 1.0 起不再沿用这一惯例。与之配套的另一条约定是从 Scrapy 1.0 开始所有发布版都应被视为生产就绪production-ready不存在奇数版不稳定的说法。当前仓库的版本号是如何实现的结合源码可以看到版本号的定义与读取链路非常简洁版本号本身集中存储在 scrapy/VERSION 文件中当前仓库中的内容为2.18.0。包初始化文件 scrapy/init.py 在导入时读取该文件并解析__version__ (pkgutil.get_data(__package__, VERSION) or b).decode(ascii).strip() version_info tuple(int(v) if v.isdigit() else v for v in __version__.split(.))version_info的解析方式值得注意它把能转成整数的段转成int其余部分比如开发版的1.3dev这类非数字段原样保留为字符串因此dev后缀版本也能被正确解析。这也解释了前文开发版不遵循三段式的说法VERSION文件是纯文本既可以写2.18.0也可以写2.19dev加载逻辑对两者都兼容。命令行中可通过scrapy version命令对应 scrapy/commands/version.py随时查看当前安装环境的版本号。API 稳定性1.0 之后的核心承诺API 稳定性API stability是 Scrapy 1.0 发布的主要目标之一。原文档给出两条判断准则单下划线前缀 私有。以单个下划线_开头的函数或方法被视为私有实现不应依赖其长期稳定。例如scrapy/core/downloader/下的_base_http.py、_base_streaming.py等模块名以及 scrapy/utils/deprecate.py 中的_clspath()这类辅助函数都属于此类——它们随时可能在下一个发布版中被重命名或删除。稳定不等于完整。稳定的 API 可以随版本增长出新的方法或功能但已存在的成员应保持行为不变。换言之Scrapy 承诺的是不悄悄破坏而不是不扩展。弃用策略至少一年的过渡期原文档的弃用政策Deprecation policy可以概括为三点过渡期承诺被弃用的 Scrapy 功能至少会被支持1 年。举例若某功能在 2020 年 6 月 15 日发布的版本中被弃用则该功能在 2021 年 6 月 14 日及之前发布的版本中仍应可用。移除时机一年后的任何新版本可以移除该弃用功能。移除必公示每个版本中移除的所有弃用功能都会明确列在 发布说明 中。在 docs/news.rst 中可以找到大量符合此策略的真实案例例如CrawlerRunner的from_crawler()之外的旧式from_settings()用法被弃用Deprecations 小节若干在 deprecated in Scrapy 2.5.0 / 2.8.0 / 2.9.0 / 2.10.0 / 2.11.0 中弃用的 API在后续版本的 Deprecation removals 小节中被正式移除。这些记录表明弃用 → 至少一年支持 → 移除并在发布说明中注明的流程在项目中是被严格执行的。源码级实现弃用机制是如何落地的文档中弃用功能的承诺在代码层面有一套完整的实现体系主要由 scrapy/exceptions.py 与 scrapy/utils/deprecate.py 两个文件承载。自定义警告类别ScrapyDeprecationWarningPython 内置的DeprecationWarning默认被解释器静默只在__main__中显示这会导致弃用提示用户根本看不到。Scrapy 为此定义了专门的警告类别class ScrapyDeprecationWarning(Warning): Warning category for deprecated features, since the default :exc:DeprecationWarning is silenced. 所有弃用警告统一使用这个类别抛出用户只需在settings或代码中对该类别做一次warnings.filterwarnings配置即可精确控制弃用提示的显示策略而不会被第三方库如 Twisted的弃用噪音干扰——事实上 scrapy/init.py 中就显式忽略了 Twisted 模块的DeprecationWarning。弃用类工厂create_deprecated_class当 Scrapy 需要重命名一个基类时比如把ScrapyClientContextFactory改名迁移直接删除旧类会瞬间破坏所有继承它的用户代码。scrapy/utils/deprecate.py 中的create_deprecated_class()解决了这个问题其行为是旧类名被替换为一个弃用壳类指向新的实现类用户代码若继承旧类名会在首次子类化时收到一次性警告warning only on first subclass, there may be others直接实例化旧类名时每次都会收到警告关键的是它重写了__subclasscheck__/__instancecheck__使得isinstance(sub(), OldName)/issubclass(sub, OldName)对新类的子类依然返回True保证基于类型判断的既有代码不会立即失效。该机制在仓库中有真实使用实例例如 scrapy/core/downloader/contextfactory.py 中的ScrapyClientContextFactory create_deprecated_class(...)以及 scrapy/core/downloader/tls.py 中的ScrapyClientTLSOptions弃用壳。路径迁移规则update_classpath 与 DEPRECATION_RULES当类被整体移动到新模块时如从scrapy.core.downloader.contextfactory迁往scrapy.core.downloader.tls设置项里配置的字符串路径需要被重定向。scrapy/utils/deprecate.py 提供了基于前缀替换的路径迁移表DEPRECATION_RULES: list[tuple[str, str]] [] def update_classpath(path: Any) - Any: Update a deprecated path from an object with its new location for prefix, replacement in DEPRECATION_RULES: if isinstance(path, str) and path.startswith(prefix): new_path path.replace(prefix, replacement, 1) warnings.warn( f{path} class is deprecated, use {new_path} instead, ScrapyDeprecationWarning, stacklevel2, ) return new_path return pathDEPRECATION_RULES是一个(旧前缀, 新前缀)二元组列表加载组件时若配置路径命中旧前缀就自动改写为新路径并抛出ScrapyDeprecationWarning明确告知用户应该更新哪个设置。这意味着即使你的settings.py中仍写着旧模块路径Scrapy 也不会直接报ImportError而是先带着警告继续工作——这正是弃用至少支持一年策略在配置加载层的直接体现。其他弃用辅助函数scrapy/utils/deprecate.py 中还提供了attribute(obj, oldattr, newattr, version)当用户访问已改名的属性时抛出警告见 L16-L23method_is_overridden(subclass, base_class, method_name)基于__code__对象同一性判断某方法是否被子类重写供仅在你重写了该旧接口时才提示弃用的场景使用argument_is_required(func, arg_name)2.14 新增判断函数参数是否必填服务于签名演进时的兼容性检查warn_on_deprecated_spider_attribute(...)见 L228-L235针对 Spider 上被弃用的属性建议改用Spider.custom_settings或Spider.update_settings()的专项警告。从源码结构看这些工具函数共同构成了弃用期的完整基础设施警告有独立类别、类有软迁移壳、路径有自动重定向、属性有访问陷阱——与文档承诺的一年过渡期 发布说明公示形成闭环。实战建议升级 Scrapy 前如何自查基于文档承诺与仓库实现升级前可执行如下检查确认当前与目标版本scrapy version版本号来自 scrapy/VERSION。通读目标版本的发布说明重点看 docs/news.rst 中对应版本的Backward-incompatible changes与Deprecation removals小节。若你的代码使用了被移除项例如旧的下划线接口、被删掉的命令行选项必须先改造再升级。打开弃用警告在测试环境中将ScrapyDeprecationWarning设为可见如-W always::scrapy.exceptions.ScrapyDeprecationWarning或warnings.filterwarnings运行完整爬取流程收集所有命中项——这些就是你应当在新大版本之前完成的迁移清单。不依赖下划线 API审查项目代码与设置中是否引用了_开头的函数/方法或内部模块如scrapy.utils.deprecate._clspath。按 API 稳定性约定这些随时可能变化。区分生产版与开发版x.y式发布可视为生产就绪dev后缀版本仅用于尝鲜和提前反馈问题不应直接上生产。小结Scrapy 的版本管理由三条规则支撑A.B.C 三段式中主版本极少动、发布号可能含破坏性变更、修复号仅修 bug1.0 之后所有版本生产就绪、单下划线 API 不承诺稳定弃用功能至少支持一年且移除必在发布说明中公示。仓库源码VERSION 文件、ScrapyDeprecationWarning、deprecate 工具模块证明这些承诺有具体的实现机制在背后保障。遵循读发布说明、开弃用警告、不碰下划线 API三步法即可在 Scrapy 大版本升级时保持代码库的平稳迁移。【免费下载链接】scrapyScrapy, a fast high-level web crawling scraping framework for Python.项目地址: https://gitcode.com/GitHub_Trending/sc/scrapy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表