How do I check which version of Python is running my script?
The current thread is about checking python version from a python program/script. In case you are looking to check the version of python interpreter installed on your machine from command line then please refer to the following post — Which version of Python do I have installed?
27 Answers 27
This information is available in the sys.version string in the sys module:
>>> print(sys.version) # parentheses necessary in python 3. 2.5.2 (r252:60911, Jul 31 2008, 17:28:52) [GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]
>>> sys.version_info (2, 5, 2, 'final', 0) # or >>> sys.hexversion 34014192
To ensure a script runs with a minimal version requirement of the Python interpreter add this to your code:
assert sys.version_info >= (2, 5)
This compares major and minor version information. Add micro (= 0 , 1 , etc) and even releaselevel (= ‘alpha’ , ‘final’ , etc) to the tuple as you like. Note however, that it is almost always better to «duck» check if a certain feature is there, and if not, workaround (or bail out). Sometimes features go away in newer releases, being replaced by others.
it’s actually the syntax for print. not for checking the version. i use that in my python 2 and 3 scripts: PY3 = sys.version_info[0] == 3
You can also access some of the fields in sys.version_info as properties, so PY3 = sys.version_info.major == 3 might be a little more appealing.
@gcb your code snippet will break whenever Python 4 happens. You should do if sys.version_info >= (3,) . It’s totally pythonic to compare different sized tuples and it’ll do the right thing.
If the python file is run with -O or -OO , the assert will be removed. So, it might be better to make a regular if check and exit the program if the condition is not fulfilled.
From the command line (note the capital ‘V’):
This is documented in ‘man python’.
@AxelBregnsbo Note that !python -V may return a different version of Python than is currently running.
from platform import python_version print(python_version()) # 3.9.2
I like sys.hexversion for stuff like this.
>>> import sys >>> sys.hexversion 33883376 >>> '%x' % sys.hexversion '20504f0' >>> sys.hexversion < 0x02060000 True
@0xC0000022L Had you ever wondered how you would be able to compare the text from the tuple? How does 'final' compares to beta, rc, or whatever it could be there. Instead if you have a numeric value, you will always be able to specify an exact version.
@sorin: uhm, that doesn't exactly matter, does it? If I compare against (2,6,4) the 'final' doesn't seem to affect the comparison and it isn't supposed to. Apparently no slicing is needed when I compare the "most significant" parts of the tuple. This seems to be how it's treated and that's what my question was about. I'm not saying this solution doesn't have its merit, I'm just wondering why it's the best - i.e. what I am missing.
The release level is defined to be one of 'alpha', 'beta', 'candidate', or 'final' which also happens to be compare correctly.
Your best bet is probably something like so:
>>> import sys >>> sys.version_info (2, 6, 4, 'final', 0) >>> if not sys.version_info[:2] == (2, 6): . print "Error, I need python 2.6" . else: . from my_module import twoPointSixCode >>>
Additionally, you can always wrap your imports in a simple try, which should catch syntax errors. And, to @Heikki's point, this code will be compatible with much older versions of python:
>>> try: . from my_module import twoPointSixCode . except Exception: . print "can't import, probably because your python is too old!" >>>
@deadly - ImportError won't catch SyntaxErrors, which will be thrown if you try to use a new syntax in an old python, such as trying to use the shortcut conditional in pre-2.5.
@Fermiparadox - Being broad keeps the assumptions low. The except Exception: line by itself already assumes a modern (2.x+) python. Maybe some future python will rearrange exception names in some backward-incompatible way? (Probably not, but who knows what python will look like in 20 years when we all have oculus rift eyeball implants? Code lasts a long time.)
#!/usr/bin/env/python import sys if sys.version_info
at the top of your script.
Note that depending on what else is in your script, older versions of python than the target may not be able to even load the script, so won't get far enough to report this error. As a workaround, you can run the above in a script that imports the script with the more modern code.
This is incorrect (or at least, incomplete) because the old interpreters will barf on newer language constructs such as x if Pred() else y . They will die during the "lexing" phase, and never have a chance to actually execute exit(1) . Seth's answer is correct in encapsulating the new language features in other files.
@MarkRushakoff: your comment is confusing. Which aspect of this answer is wrong? The missing else branch or that a < is used for version_info ? AFAIK Python pads missing values in tuples, and all of this should be valid before 2.6, no? So Seth's answer uses slicing (redundantly) while this one doesn't and that makes your comment even more confusing.
I think what @MarkRushakoff is saying is that if you have this at the top of a file, and a new language feature elsewhere in the same file, the old version of python will die when loading the file, before it runs any of it, so the error won't be shown. Basically you have to put the above (or another check) at the top of a file, then import the code that requires a new version of python from separate files.
Here's a short commandline version which exits straight away (handy for scripts and automated execution):
python -c "print(__import__('sys').version)"
Or just the major, minor and micro:
python -c "print(__import__('sys').version_info[:1])" # (2,) python -c "print(__import__('sys').version_info[:2])" # (2, 7) python -c "print(__import__('sys').version_info[:3])" # (2, 7, 6)
Nice, this solves my problem where I was getting the version number by capturing the output of python2 --version and python3 --version from PHP. While I would get the latter without problems via passthru() , the former would only print to screen but never be captured, even when redirected into a file.
In my case that would be more of the same as I'm already redirecting the passthru() output to a file. Your solution does exactly what I need. 🙂
Thank you. Also in my case it was usefull to add assert to validate version with exit code python -c "assert __import__('sys').version_info[:2] >= (3, 6)"
With six module, you can do it by:
import six if six.PY2: # this is python2.x else: # six.PY3 # this is python3.x
import sys sys.version.split(' ')[0]
sys.version gives you what you want, just pick the first number 🙂
Like Seth said, the main script could check sys.version_info (but note that that didn't appear until 2.0, so if you want to support older versions you would need to check another version property of the sys module).
But you still need to take care of not using any Python language features in the file that are not available in older Python versions. For example, this is allowed in Python 2.5 and later:
try: pass except: pass finally: pass
but won't work in older Python versions, because you could only have except OR finally match the try. So for compatibility with older Python versions you need to write:
try: try: pass except: pass finally: pass
Several answers already suggest how to query the current python version. To check programmatically the version requirements, I'd make use of one of the following two methods:
# Method 1: (see krawyoti's answer) import sys assert(sys.version_info >= (2,6)) # Method 2: import platform from distutils.version import StrictVersion assert(StrictVersion(platform.python_version()) >= "2.6")
Just for fun, the following is a way of doing it on CPython 1.0-3.7b2, Pypy, Jython and Micropython. This is more of a curiosity than a way of doing it in modern code. I wrote it as part of http://stromberg.dnsalias.org/~strombrg/pythons/ , which is a script for testing a snippet of code on many versions of python at once, so you can easily get a feel for what python features are compatible with what versions of python:
via_platform = 0 check_sys = 0 via_sys_version_info = 0 via_sys_version = 0 test_sys = 0 try: import platform except (ImportError, NameError): # We have no platform module - try to get the info via the sys module check_sys = 1 if not check_sys: if hasattr(platform, "python_version"): via_platform = 1 else: check_sys = 1 if check_sys: try: import sys test_sys = 1 except (ImportError, NameError): # just let via_sys_version_info and via_sys_version remain False - we have no sys module pass if test_sys: if hasattr(sys, "version_info"): via_sys_version_info = 1 elif hasattr(sys, "version"): via_sys_version = 1 else: # just let via_sys remain False pass if via_platform: # This gives pretty good info, but is not available in older interpreters. Also, micropython has a # platform module that does not really contain anything. print(platform.python_version()) elif via_sys_version_info: # This is compatible with some older interpreters, but does not give quite as much info. print("%s.%s.%s" % sys.version_info[:3]) elif via_sys_version: import string # This is compatible with some older interpreters, but does not give quite as much info. verbose_version = sys.version version_list = string.split(verbose_version) print(version_list[0]) else: print("unknown")
What version of Python do I have?
@TejasKale Better to run ls /usr/bin/python* (or ls /usr/bin/*python* if you really want files with python anywhere in the name). That way, ls still formats its output for a terminal (and you get multiple columns and, with the default ls alias in Ubuntu, colorization).
9 Answers 9
You can use python -V (et al.) to show you the version of Python that the python command resolves to. If that's all you need, you're done. But to see every version of python in your system takes a bit more.
In Ubuntu we can check the resolution with readlink -f $(which python) . In default cases in 14.04 this will simply point to /usr/bin/python2.7 .
We can chain this in to show the version of that version of Python:
$ readlink -f $(which python) | xargs -I % sh -c 'echo -n "%: "; % -V' /usr/bin/python2.7: Python 2.7.6
But this is still only telling us what our current python resolution is. If we were in a Virtualenv (a common Python stack management system) python might resolve to a different version:
$ readlink -f $(which python) | xargs -I % sh -c 'echo -n "%: "; % -V' /home/oli/venv/bin/python: Python 2.7.4
The fact is there could be hundreds of different versions of Python secreted around your system, either on paths that are contextually added, or living under different binary names (like python3 ).
If we assume that a Python binary is always going to be called python and be a binary file, we can just search the entire system for files that match those criteria:
$ sudo find / -type f -executable -iname 'python*' -exec file -i '<>' \; | awk -F: '/x-executable; charset=binary/ ' | xargs readlink -f | sort -u | xargs -I % sh -c 'echo -n "%: "; % -V' /home/oli/venv/bin/python: Python 2.7.4 /media/ned/websites/venvold/bin/python: Python 2.7.4 /srv/chroot/precise_i386/usr/bin/python2.7: Python 2.7.3 /srv/chroot/trusty_i386/usr/bin/python2.7: Python 2.7.6 /srv/chroot/trusty_i386/usr/bin/python3.4: Python 3.4.0 /srv/chroot/trusty_i386/usr/bin/python3.4m: Python 3.4.0 /usr/bin/python2.7: Python 2.7.6 /usr/bin/python2.7-dbg: Python 2.7.6 /usr/bin/python3.4: Python 3.4.0 /usr/bin/python3.4dm: Python 3.4.0 /usr/bin/python3.4m: Python 3.4.0 /web/venvold/bin/python: Python 2.7.4
It's obviously a pretty hideous command but this is again real output and it seems to have done a fairly thorough job.