Is sys.version_info reliable for Python version checking?

Is sys.version_info reliable for Python version checking?



If I'm making a module that I would like to run the same in Python 2 as in Python 3, there are a ton of options including six, futures, and 2to3. If the number of changes is small though, each of those tools has enough quirks that I tend to prefer to just write a compatibility interface for the few incompatible functions my module actually uses.


six


futures


2to3



A reasonably standard way to accomplish that is with a straightforward version check.


import module_bar

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



Are there any oddball cases where sys.version_info wouldn't be reported correctly though? I've been bitten enough in the past by malformed paths, configs, installations, modifications, and whatnot that this doesn't feel like a thing I should trust.


sys.version_info



When we get right down to it, what I actually care about is if a particular feature is implemented. In web development, it's generally recognized as a bad practice to sniff user-agents. Instead, one should do their best to identify if a particular feature is in use or not. Depending on the feature, there are many ways one could accomplish that.


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



On my machine, the second route is twice as slow (not that an extra few hundred nanoseconds really matter for a one-time operation), but it doesn't seem to have any other major disadvantages. Are there advantages though? Are there Python installations where the second approach will be successful and the first will fail?






Yes it is. Why not?

– iBug
Sep 17 '18 at 1:42






Possible duplicate of How do I detect the Python version at runtime?

– Pedro Lobito
Sep 17 '18 at 1:46






@iBug The "why not" stems from me not knowing what I don't know here. The question (here)[stackoverflow.com/questions/22236727/… indicates that there could be problems.

– Hans Musgrave
Sep 17 '18 at 1:47






Possible dupe of stackoverflow.com/questions/1093322/…

– DYZ
Sep 17 '18 at 1:48






@Hans See the documentation: Do not extract version information out of it (sys.version), rather, use version_info and the functions provided by the platform module. See my edited answer.

– iBug
Sep 17 '18 at 1:49



sys.version




2 Answers
2



Yes. sys.version_info is a reliable way to determine Python version.


sys.version_info



See Python 3 documentation and Python 2 documentation.



Note: sys.version_info is reliable, but not sys.version:


sys.version_info


sys.version



A string containing the version number of the Python interpreter plus additional information on the build number and compiler used. This string is displayed when the interactive interpreter is started. Do not extract version information out of it, rather, use version_info and the functions provided by the platform module.


version_info


platform



If you're worried about bad modules changing the values of sys.version_info or something else, you can force a reload of <module 'sys' (built-in)>:


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, ...






The "Do not extract version information out of it" warning is mostly because 1) you're likely to get it wrong, and 2) the information is available through more convenient, safer options that don't require you to parse anything.

– user2357112
Sep 17 '18 at 1:59






@user2357112 Well, that's what Python doc says.

– iBug
Sep 17 '18 at 2:05






@user2357112 I'd wager a bet that it's partially also because they're not promising formatting compatibility between minor versions.

– Hans Musgrave
Sep 17 '18 at 2:12






@iBug I like the fact that you fixed the bad_dependency problem, but sys.modules.pop isn't really safe if any other modules in that python instance depend on sys. Using imp.reload is fine for now, but deprecated for 3.4+. Arguably imp.reload will be around for as long as anyone really cares about 2/3 compatibility. Do you think that's a good enough cross-version solution?

– Hans Musgrave
Sep 17 '18 at 2:30


bad_dependency


sys.modules.pop


sys


imp.reload


imp.reload






@Hans importlib.reload(sys) doesn't work. I just tested this on Python 3.6.

– iBug
Sep 17 '18 at 2:43


importlib.reload(sys)



No, sys.version_info is not reliable, but only in the sense that almost everything in Python is overwriteable and because of how modules are singletons if no voodoo is being done. Consider the following example, which has one tiny typo.


sys.version_info


# bad_dependency.py
import sys

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



What happens when we import this? Well...nothing good.


# our_module.py
import sys
import bad_dependency

print(sys.version_info)



When we run this, since sys is the same module everywhere and since we've overwritten the information we care about, we actually get the following behavior:


sys


$ python our_module.py
(3,)



Of course by this metric almost none of our code is reliable if our imports have bad enough bugs. What's interesting is that it doesn't have to be our code that causes the problem, and the effects certainly don't need to be malicious.



As to the question of whether problems like this exist by default in some reasonably standard Python installations (e.g., micropython, OSX, etc...), I'm still not sure of the answer.






See my edited answer for defending against bad_dependency.

– iBug
Sep 17 '18 at 2:16


bad_dependency






@iBug I like that idea. I'm still holding out for anyone who knows of platforms with an incorrect sys.version_info (proving a negative is hard), but in a day or two I'll otherwise select yours as the best answer.

– Hans Musgrave
Sep 17 '18 at 2:32


sys.version_info



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)