sys.version_info 对于 Python 版本检查是否可靠?

新手上路,请多包涵

如果我正在制作一个模块,我想在 Python 2 和 Python 3 中运行相同的模块,则有大量选项,包括 sixfutures2to3 。如果更改的数量很小,那么这些工具中的每一个都有足够的怪癖,我倾向于只为我的模块实际使用的几个不兼容的函数编写一个兼容接口。

一个合理的标准方法是通过简单的版本检查来实现这一点。

 import module_bar

if sys.version_info >= (3,):
    uniformly_named_foo = module_bar.py3_thing
else:
    uniformly_named_foo = module_bar.py2_thing

是否有任何奇怪的情况 sys.version_info 不会被正确报告?在过去,我已经被格式错误的路径、配置、安装、修改等等所困扰,以至于我觉得这不像是我应该信任的东西。

当我们认真对待它时, 我真正关心的是是否实现了特定功能。在 Web 开发中,嗅探用户代理通常被认为是一种不好的做法。相反,人们应该尽最大努力确定某个特定功能是否在使用中。根据功能的不同,可以通过多种方式实现这一目标。

 if hasattr(module_bar, 'py3_thing'):
    uniformly_named_foo = module_bar.py3_thing
else:
    uniformly_named_foo = module_bar.py2_thing

在我的机器上,第二条路线慢了一倍(并不是说额外的几百纳秒对于一次性操作来说真的很重要),但它似乎没有任何其他主要缺点。有优势吗? 是否存在第二种方法会成功而第一种方法会失败的 Python 安装?

原文由 Hans Musgrave 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 533
2 个回答

是的。 sys.version_info 是确定 Python 版本的可靠方法。

请参阅 Python 3 文档Python 2 文档

注意: sys.version_info 是可靠的,但不是 sys.version

系统版本

一个字符串,包含 Python 解释器的版本号以及有关构建号和所用编译器的附加信息。该字符串在交互式解释器启动时显示。 不要从中提取版本信息,而是使用 version_infoplatform 模块提供的功能。

如果您担心坏模块会更改 sys.version_info 或其他值,您可以 强制重新加载 <module 'sys' (built-in)>

 import sys
sys.version_info = "boo"
print(sys.version_info)  # boo

sys.modules.pop("sys")
import sys  # reloaded
print(sys.version_info)
# Output: sys.version_info(major=3, minor=6, ...

原文由 iBug 发布,翻译遵循 CC BY-SA 4.0 许可协议

不, sys.version_info 不可靠,但仅在 Python 中的几乎所有内容都是可覆盖的意义上,并且因为如果不执行巫术,模块是单例的。考虑以下示例,其中有一个小错字。

 # bad_dependency.py
import sys

# is_py3 = sys.version_info >= (3,)
is_py3 = sys.version_info = (3,)

当我们导入这个时会发生什么?嗯……没什么好说的。

 # our_module.py
import sys
import bad_dependency

print(sys.version_info)

当我们运行它时,由于 sys 到处都是相同的模块,并且由于我们已经覆盖了我们关心的信息,所以我们实际上得到以下行为:

 $ python our_module.py
(3,)

当然,根据这个指标,如果我们的导入有足够严重的错误,我们的代码几乎都不可靠。有趣的是,导致问题的不一定是我们的代码,而且效果当然不需要是恶意的。

至于在某些相当标准的 Python 安装(例如 micropython、OSX 等)中是否默认存在这样的问题,我仍然不确定答案。

原文由 Hans Musgrave 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题