惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tenable Blog
博客园_首页
Vercel News
Vercel News
WordPress大学
WordPress大学
美团技术团队
G
Google Developers Blog
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Y
Y Combinator Blog
博客园 - 【当耐特】
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
The Cloudflare Blog
T
The Blog of Author Tim Ferriss
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google DeepMind News
Google DeepMind News
云风的 BLOG
云风的 BLOG
腾讯CDC
M
MIT News - Artificial intelligence
爱范儿
爱范儿
Recent Announcements
Recent Announcements
雷峰网
雷峰网
Last Week in AI
Last Week in AI
宝玉的分享
宝玉的分享
The Register - Security
The Register - Security
Jina AI
Jina AI
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Hugging Face - Blog
Hugging Face - Blog
P
Privacy & Cybersecurity Law Blog
Recorded Future
Recorded Future
Help Net Security
Help Net Security
N
News and Events Feed by Topic
博客园 - Franky
P
Proofpoint News Feed
L
LINUX DO - 热门话题
S
SegmentFault 最新的问题
The GitHub Blog
The GitHub Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
月光博客
月光博客
D
Docker
Google DeepMind News
Google DeepMind News
有赞技术团队
有赞技术团队
IT之家
IT之家
Security Latest
Security Latest
L
LangChain Blog
V
V2EX
阮一峰的网络日志
阮一峰的网络日志
J
Java Code Geeks

Tab Completion

Tab Completion Tab Completion Tab Completion Tab Completion
Tab Completion
2022-02-18 · via Tab Completion

Python has four obvious built-in ways to retrieve its current version. If your software has a minimum version requirement, you'll use one of these methods to test whether the Python currently running your code is a high-enough version to do so successfully.

Three of these ways are worthless, actively-harmful traps. If you read nothing else, read this: use sys.version_info.

The four ways are:

  • sys.version_info is the good way, returning a tuple of numbers, one for each component of the version
  • sys.version is a terrible way, returning a string containing the full version identifier
  • platform.python_version() is another terrible way, also returning a string
  • platform.python_version_tuple() is a final and especially terrible way, returning A TUPLE OF GODDAM STRINGS FOR THE COMPONENTS

Deets

sys.version_info returns a tuple of numeric components. Well, it returns a namedtuple, but same deal. If I convert it to a plain tuple, on my system I get:

(3, 7, 12, 'final', 0)

Tuples in Python have nice sorting behavior; they'll compare against other tuples element-wise, with missing items considered as coming before present items. This means that if I write sys.version_info >= (3, 7), it'll be true - the 3 and 7 match, then the remaining components in sys.version mean it's slightly greater than the (3, 7) literal.

Importantly, because this uses element-wise comparison and the elements are (mostly) numbers, it won't fail for stupid reasons, like version 3.10 coming out. If you compare (3, 10) >= (3, 7) it correctly returns True, because 10 is greater than 7.


platform.python_version_tuple() also returns a tuple of components, but each component is a string. Currently on my system it returns ('3', '7', '12').

If you compare it with a literal tuple, like platform.python_version_tuple() >= ('3', '7') (note that you have to write the literal with strings, or else it'll error), it'll appear to work - you'll get back True. If the function returns ('3', '6') or ('3', '8') it also appears to do the right thing, returning False and True respectively. Bump it to ('3', '9') and it's still True, as expected. But advance to ('3', '10') and it suddenly returns False, indicating that version 3.10 is less than version 3.7.

This is because string-wise comparison is not the same as numerical comparison. Strings compare letter-by-letter, and "1" (the first letter of "10") is indeed less than "7", and so fails the >= check.

This is a very easy mistake for end-users to make. It's an unforgiveable mistake for Python, the language, to make. Returning a tuple, indicating it's been parsed, but filling that tuple with strings when they know the components are numeric and will be used as if they were numbers, is just absolute clown-shoes behavior.


sys.version and platform.python_version() just straight up return strings. Once again, naive comparison seems to work: on my system sys.version returns '3.7.12 (default, Nov 11 2021, 11:50:43) \n[GCC 10.3.0]', and if you run sys.version >= '3.7', it returns True as expected.

Both of these fail when the version is 3.10, in the exact same way as platform.python_version_tuple().

Conclusion

Always, always, ALWAYS use sys.version_info to get the current Python version, for any purpose. Anything else will break your code for stupid reasons.