How do I detect the Python version at runtime? [duplicate]
Asked Answered
D

9

487

I have a Python file which might have to support Python versions < 3.x and >= 3.x. Is there a way to introspect the Python runtime to know the version which it is running (for example, 2.6 or 3.2.x)?

Dissatisfied answered 31/1, 2012 at 11:50 Comment(1)
do import sys; print(sys.version) output 3.9.6 (default, Aug 18 2021, 12:38:10) [Clang 10.0.0 ]Aeroballistics
M
737

Sure, take a look at sys.version and sys.version_info.

For example, to check that you are running Python 3.x, use

import sys
if sys.version_info[0] < 3:
    raise Exception("Must be using Python 3")

Here, sys.version_info[0] is the major version number. sys.version_info[1] would give you the minor version number.

In Python 2.7 and later, the components of sys.version_info can also be accessed by name, so the major version number is sys.version_info.major.

See also How can I check for Python version in a program that uses new language features?

Martyr answered 31/1, 2012 at 11:52 Comment(9)
Don't check the value of sys.version. Only use it for displaying purposes.Orfinger
@Orfinger please explain why sys.version should not be checked.Karlie
@Karlie sys.version is meant to be displayed to users. It's not a program-friendly interface and therefore Do not extract version information out of it (as said by Python Documentation).Orfinger
@Orfinger is correct. The documentation specifically says to instead use sys.version_info for our purpose here. docs.python.org/3/library/sys.html#sys.versionSenegal
The returned value is not an integer, so I had to cast it in order to perform comparison: if int(sys.version[0]) < 3:.Allotrope
You can compare it to a tuple like sys.version_info >= (3,8,5) or sys.version_info >= (3,8), but note that version 3.8.5 is not equal to (3,8) because it compares all the values in version_info, which are major, minor, micro, releaselevel, and serial according to the documentation.Peashooter
I find it more readable to use the named attribute: sys.version_info.major than to use indexes.Balkan
And what about PY_VERSION_HEX ? docs.python.org/3/c-api/apiabiversion.html#apiabiversionBanter
Better to use sys.version_info.major > 2 and sys.version_info.minor >7Rabb
G
155

Try this code, this should work:

import platform
print(platform.python_version())
Georgie answered 11/1, 2017 at 10:21 Comment(6)
FYI this works, but the python_version function returns a string (e.g. on my system it prints '3.6.1'). If you're checking the version in an if statement like the OP is, Chris' answer makes much more sense, as you don't have to go through the clunky process of searching the string for the desired info. This answer is the way to go if you want to log or display the version to be read by a human.Adna
@Adna Chris's answer also returns a string, he's just indexing into the first character to see if it is '3' or not; the same would work here.Hillell
Hoe does this solve the problem better, if not at all? Using sys.version_info[0] or just sys.version[0] is already enough ...Oat
If you want each element in the version number as an int, you can use platform.python_version_tuple(). This method may be preferable over sys.version_info because: "unlike the Python sys.version, the returned value will always include the patchlevel"Zins
@weberc2, Chris's answer doesn't return a string, at least not the sys.version_info option. That is actually a sys.version_info type which happens to be indexible. (Of course, sys.version is a str.)Kirkland
@jdk1.0 Ah, good find. I stand corrected. :)Hillell
F
32

Per sys.hexversion and API and ABI Versioning:

import sys
if sys.hexversion >= 0x3000000:
    print('Python 3.x hexversion %s is in use.' % hex(sys.hexversion))
Frederiksen answered 31/1, 2012 at 11:52 Comment(4)
As this allows testing both major and minor versions in a single simple and easy-to-read test, I think this is the best answer.Juxtapose
You can also do something like if sys.version_info >= (3,6,0) because tuples are directly comparable.Wary
@Wary , I think your answer is the quickest, most concise, and easiest-understand. You should post it as an answer.Miltiades
Unfortunately I can't add an answer to this question - maybe it's too old, or maybe because it's marked as a duplicate?Wary
M
21

Just in case you want to see all of the gory details in human readable form, you can use:

from sys import version as python_formatted_version

print(python_formatted_version)

Output for my system:

3.6.5 |Anaconda, Inc.| (default, Apr 29 2018, 16:14:56) 
[GCC 7.2.0]

Something very detailed but machine parsable would be to get the version_info object from sys, instead, and then use its properties to take a predetermined course of action.

For example:

from sys import version_info as python_version_info

print(python_version_info)

Output on my system:

sys.version_info(major=3, minor=6, micro=5, releaselevel='final', serial=0)
Mudd answered 7/5, 2018 at 0:22 Comment(1)
Corrected and updated based on above comment. Thank you!Mudd
B
17

The best solution depends on how much code is incompatible. If there are a lot of places you need to support Python 2 and 3, six is the compatibility module. six.PY2 and six.PY3 are two booleans if you want to check the version.

However, a better solution than using a lot of if statements is to use six compatibility functions if possible. Hypothetically, if Python 3000 has a new syntax for next, someone could update six so your old code would still work.

import six

# OK
if six.PY2:
  x = it.next() # Python 2 syntax
else:
  x = next(it) # Python 3 syntax

# Better
x = six.next(it)

http://pythonhosted.org/six/

Balfore answered 18/4, 2017 at 19:53 Comment(0)
S
12

Here's some code I use with sys.version_info to check the Python installation:

def check_installation(rv):
    current_version = sys.version_info
    if current_version[0] == rv[0] and current_version[1] >= rv[1]:
        pass
    else:
        sys.stderr.write( "[%s] - Error: Your Python interpreter must be %d.%d or greater (within major version %d)\n" % (sys.argv[0], rv[0], rv[1], rv[0]) )
        sys.exit(-1)
    return 0

...

# Calling the 'check_installation' function checks if Python is >= 2.7 and < 3
required_version = (2,7)
check_installation(required_version)
Strongroom answered 31/1, 2012 at 11:59 Comment(0)
P
2

Version check example below.

Note that I do not stop the execution, this snippet just:
- do nothing if exact version matches
- write INFO if revision (last number) is different
- write WARN if any of major+minor are different

import sys
import warnings

def checkVersion():
    # Checking Python version:
    expect_major = 2
    expect_minor = 7
    expect_rev = 14
    if sys.version_info[:3] != (expect_major, expect_minor, expect_rev):
        print("INFO: Script developed and tested with Python " + str(expect_major) + "." + str(expect_minor) + "." + str(expect_rev))
        current_version = str(sys.version_info[0])+"."+str(sys.version_info[1])+"."+str(sys.version_info[2])
        if sys.version_info[:2] != (expect_major, expect_minor):
            warnings.warn("Current Python version was unexpected: Python " + current_version)
        else:
            print("      Current version is different: Python " + current_version)
Paean answered 15/2, 2018 at 9:3 Comment(0)
V
1

To make the scripts compatible with Python2 and 3 i use :

from sys import version_info
if version_info[0] < 3:
    from __future__ import print_function
Vat answered 10/3, 2016 at 10:26 Comment(2)
This is unnecessary, just add from__future__ import print_function without the version check. The import does nothing in Python 3.Superstitious
This code doesn’t even work, it’s a SyntaxError because from __future__ imports must occur at the very top of the file.Motherly
C
0

Since all you are interested in is whether you have Python 2 or 3, a bit hackish but definitely the simplest and 100% working way of doing that would be as follows: python python_version_major = 3/2*2 The only drawback of this is that when there is Python 4, it will probably still give you 3.

Counterclaim answered 27/4, 2018 at 23:49 Comment(1)
This code gives the wrong answers after futurizing it.Euphonious

© 2022 - 2024 — McMap. All rights reserved.