Compatibility with Python 2 and Python 3¶
Starting with EasyBuild v4.0, the EasyBuild framework and easyblocks are compatible with both Python versions 2 and 3. More specifically, the following Python versions are currently supported:
- Python 2.6.x (support was removed in EasyBuild v4.4.0)
- Python 2.7.x (support will be removed in EasyBuild v5.0.0)
- Python 3.5.x (support will be removed in EasyBuild v5.0.0)
- Python 3.6.x
- Python 3.7.x
- Python 3.8.x (requires EasyBuild v4.1.0)
- Python 3.9.x (requires EasyBuild v4.3.1)
- Python 3.10.x (requires EasyBuild v4.5.2)
- Python 3.11.x (requires EasyBuild v4.5.2)
Determining which Python version EasyBuild is using via $EB_VERBOSE¶
To determine which Python version is being used to run EasyBuild, you
can define the $EB_VERBOSE environment variable.
For example:
$ export EB_VERBOSE=1
$ eb --version
>> Considering 'python'...
>> No 'python' found in $PATH, skipping...
>> Considering 'python3'...
>> 'python3' version: 3.6.9, which matches Python 3 version requirement (>= 3.5)
>> Selected Python command: python3 (/usr/local/bin/python3)
>> python3 -m easybuild.main --version
This is EasyBuild 4.0.0 (framework: 4.0.0, easyblocks: 4.0.0) on host example.
Controlling which python command EasyBuild will use via $EB_PYTHON¶
The eb command will consider different python commands, and check
the Python version corresponding with the command before selecting one.
The commands considered are (in order):
pythonpython3python2
Before considering these commands, eb will first consider the command
name specified via the $EB_PYTHON environment variable (if defined),
so you can always control which Python version is being used if desired.
For example:
$ export EB_PYTHON=python3.7
$ export EB_VERBOSE=1
$ eb --version
>> Considering 'python3.7'...
>> 'python3.7' version: 3.7.2, which matches Python 3 version requirement (>= 3.5)
>> Selected Python command: python3.7 (/usr/local/bin/python3.7)
>> python3.7 -m easybuild.main --version
This is EasyBuild 4.0.0 (framework: 4.0.0, easyblocks: 4.0.0) on host example.
The easybuild.tools.py2vs3 package¶
To facilitate this, the easybuild.tools.py2vs3 package was introduced
in EasyBuild v4.0. When importing a function from this package, you will
automatically get a version of the function that is compatible with the
Python version being used to run EasyBuild.
Through this approach we can hide subtle differences between Python 2
and 3, while avoiding code duplication and Python version checks
throughout the codebase, as well as avoid requiring packages like six
or future (which facilitate maintaining compatibility with Python 2
and 3, but are also a bit of a burden).
The easybuild.tools.py2vs3 package provides two major classes of items
(listed below in alphabetical order):
- functions from the Python standard library which should be imported from different locations in Python 2 and 3
- wrappers for functionality in the Python standard library which behaves differently in Python 2 and 3
ascii_letters¶
- Python 2: corresponds to
string.letters - Python 3: corresponds to
string.ascii_letters
ascii_lowercase¶
- Python 2: corresponds to
string.lowercase - Python 3: corresponds to
string.ascii_lowercase
build_opener¶
- Python 2: corresponds to
urllib2.build_openerfunction - Python 3: corresponds to
urllib.request.build_openerfunction
configparser¶
- Python 2: corresponds to
ConfigParser.configparsermodule - Python 3: corresponds to
configparsermodule
create_base_metaclass¶
Function to create a metaclass that can be used as a base class, implemented in a way that is compatible with both Python 2 and 3.
extract_method_name¶
Function to method name from lambda function, implemented in a way that is compatible with both Python 2 and 3.
HTTPError¶
- Python 2: corresponds to
urllib2.HTTPError - Python 3: corresponds to
urllib.request.HTTPError
HTTPSHandler¶
- Python 2: corresponds to
urllib2.HTTPSHandler - Python 3: corresponds to
urllib.request.HTTPSHandler
json_loads¶
-
Python 2: wraps
json.loadsfunction -
Python 3: wraps
json.loadsfunction, taking into account that for Python versions older than 3.6- a value of type
string(rather thanbytes) is required as argument
- a value of type
mk_wrapper_baseclass¶
Function to create a wrapper base class using the specified metaclass, implemented in a way that is compatible with both Python 2 and 3.
OrderedDict¶
- Python 2.6: corresponds to
easybuild.tools.ordereddict.OrderedDict - Python 2.7: corresponds to
collections.OrderedDict - Python 3: corresponds to
collections.OrderedDict
reload¶
- Python 2: corresponds to
reloadbuilt-in function - Python 3: corresponds to
importlib.reloadfunction
raise_with_traceback¶
Function to raise an error with specified message and traceback, implemented in a way that is compatible with both Python 2 and 3.
Request¶
- Python 2: corresponds to
urllib2.Request - Python 3: corresponds to
urllib.request.Request
subprocess_popen_text¶
- Python 2: wrapper for
subprocess.Popen - Python 3: wrapper for
subprocess.Popenwhile forcing text mode (usinguniversal_newlines=True)
std_urllib¶
- Python 2: corresponds to
urllibpackage - Python 3: corresponds to
urllib.requestpackage
string_type¶
- Python 2: corresponds to
basestringbuilt-in string type - Python 3: corresponds to
strbuilt-in string type
StringIO¶
- Python 2: corresponds to
StringIO.StringIOclass - Python 3: corresponds to
io.StringIOclass
urlencode¶
- Python 2: corresponds to
urllib.urlencodefunction - Python 3: corresponds to
urllib.parse.urlencodefunction
URLError¶
- Python 2: corresponds to
urllib2.URLError - Python 3: corresponds to
urllib.request.URLError
urlopen¶
- Python 2: corresponds to
urllib2.urlopen - Python 3: corresponds to
urllib.request.urlopen