通过警告方式的弃用对Python库不起作用。
Deprecations via warnings don't work for Python libraries

原始链接: https://sethmlarson.dev/deprecations-via-warnings-dont-work-for-python-libraries

最近 urllib3 v2.6.0 版本发布以及随后的快速修复,凸显了一个令人沮丧的问题:Python 的 `DeprecationWarning` 系统似乎无法有效提示库更新。尽管早在 2022 年就已弃用存在问题的 API,并已发出警告超过三年——甚至在一个广泛使用的软件包中——删除仍然破坏了 Kubernetes、Fastly 和 Airflow 等依赖库。 作者认为,仅依赖 `DeprecationWarning` 并不足够,因为它很容易被忽略。讨论的潜在解决方案包括创建自定义警告类以避免被过滤掉,或者干脆放弃提前通知,转而采用频繁的主要版本发布(如 Cryptography 库)。 核心问题在于,当前警告机制无法触达足够的开发者以主动解决 API 变更,使维护者陷入两难境地:破坏性变更与支持过时代码之间。

相关文章

原文

Last week urllib3 v2.6.0 was released which contained removals for several APIs that we've known were problematic since 2019 and have been deprecated since 2022. The deprecations were marked in the documentation, changelog, and what I incorrectly believed would be the most meaningful signal to users: with a DeprecationWarning being emitted for each use for the API.

The API that urllib3 recommended users use instead has the same features and no compatibility issues between urllib3 1.x and 2.x:

resp = urllib3.request("GET", "https://example.com")

# Deprecated APIs
resp.getheader("Content-Length")
resp.getheaders()

# Recommended APIs
resp.headers.get("Content-Length")
resp.headers

This API was emitting warnings for over 3 years in a top-3 Python package by downloads urging libraries and users to stop using the API and that was not enough. We still received feedback from users that this removal was unexpected and was breaking dependent libraries. We ended up adding the APIs back and creating a hurried release to fix the issue.

It's not clear to me that waiting longer would have helped, either. The libraries that were impacted are actively developed, like the Kubernetes client, Fastly client, and Airflow and I trust that if the message had reached them they would have taken action.

My conclusion from this incident is that DeprecationWarning in its current state does not work for deprecating APIs, at least for Python libraries. That is unfortunate, as DeprecationWarning and the warnings module are easy-to-use, language-“blessed”, and explicit without impacting users that don't need to take action due to deprecations. Any other method of deprecating API features is likely to be home-grown and different across each project which is far worse for users and project maintainers.

DeprecationWarning is called out in the “ignored by default” list for Python. I could ask for more Python developers to run with warnings enabled, but solutions in the form of “if only we could all just” are a folly. Maybe the answer is for each library to create its own “deprecation warning” equivalent just to not be in the “ignored by default” list:

import warnings

class Urllib3DeprecationWarning(UserWarning):
    pass

warnings.warn(
    "HTTPResponse.getheader() is deprecated",
    category=Urllib3DeprecationWarning,
    stacklevel=2
)

Maybe the answer is to do away with advance notice and adopt SemVer with many major versions, similar to how Cryptography operates for API compatibility. Let me know if you have other ideas.

Wow, you made it to the end!

联系我们 contact @ memedata.com