Feature Checking versus Version Checking2020-01-07
I always prefer explicitly checking versions instead of checking for presence of features:
1) This makes it explicit which versions supports the desired functionality, which serves as documentation and makes it easy to drop the legacy code later when that version is no longer supported: search for sys.version_info in the codebase and remove the old code.
2) In the specific case of ImportErrors, broken environments might cause an otherwise valid import to raise an error, which would then hide the real reason why the import failed. Had seen this myself a few times in "frozen" applications (cx_freeze, pyinstaller) where build problems caused ImportErrors which should not happen on that version.
I have also moved towards doing this myself, for the same reasons.
1. It’s More Explicit
Being more explicit, is the primary appeal to me. Feature-checking is normally accompanied with an explanatory comment about version numbers anyway. For example here’s some code I had in an old version of Django-MySQL:
# Django 1.11 comment contains useful information outside of code.
It could also, like any comment, be a lie.
Additionally, unless you are very disciplined in how you format such comments, it can be hard to find them all during upgrades.
With version checking, the comment becomes code:
2. It Reveals Broken Sub-Imports
The second reason, unexpected sub-import failures, is a case of bug silencing.
I’ve not worked with frozen environments as Bruno has, but it can happen in other situations.
For example, importing a Python module can fail if it tries to import a missing C library.
ImportErrors are not related to the feature check, but the other code path would be mistakenly run as well.
This 2011 post from Armin Ronacher covers the problem in depth.
It’s a good read and has a workaround “cautious import” function, which avoids catching sub-module
I hope this helps you build better Python projects that support multiple language or library versions.
© 2020 All rights reserved.