Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can all __future__ statements be removed from python code, without affecting its functionality using python 3.7.1?

Can the following __future__ statements be removed from source code, without affecting its functionality if I am using python 3.7.1?

from __future__ import nested_scopes
from __future__ import generators
from __future__ import division
from __future__ import absolute_import
from __future__ import with_statement
from __future__ import print_function
from __future__ import unicode_literals
like image 803
Alireza Avatar asked Dec 18 '18 10:12

Alireza


People also ask

What is from __ future __ in Python?

__future__ module is a built-in module in Python that is used to inherit new features that will be available in the new Python versions.. This module includes all the latest functions which were not present in the previous version in Python. And we can use this by importing the __future__ module.

What does from __ future __ import do?

The from __future__ import division directive forces the use of Python 3.0 style division.

What is __ future __ import Absolute_import?

from __future__ import absolute_import means that if you import string , Python will always look for a top-level string module, rather than current_package.string . However, it does not affect the logic Python uses to decide what file is the string module.


2 Answers

This is documented in the lib/python3.7/__future__.py file. Each future import (here called _Feature) is given two 5-tuples, specifying optional and mandatory releases, respectively. Here, "mandatory release" means which version of Python includes the feature by default. As you can see by following the link above, all mandatory versions are < 3.7.1 except two, namely barry_as_FLUFL (mandatory in version 3.9.0) and annotations (mandatory in version 4.0.0), the first of which is just an Easter egg.

All future imports on your list can then indeed be removed if using Python 3.7.1 or newer, with the exact same code execution guaranteed. As others have commented, this might not be a good idea though, as this reduces code compatibility.

like image 72
jmd_dk Avatar answered Oct 14 '22 02:10

jmd_dk


You could remove those __future__ imports without impacting functionality, but removing them is not necessary and stops compatibility with earlier python versions.

Moreover, as @deceze alludes to in his comment, other imports may be different. For example, from __future__ import annotations is only enabled in Python <= 4.0 via the import, so adding/removing that line would impact the functionality:

Since this change breaks compatibility, the new behavior needs to be enabled on a per-module basis in Python 3.7 using a __future__ import:

from __future__ import annotations

It will become the default in Python 4.0.

As @jmd_dk points out, you can actually find this information in the __future__ module. I wrote a short script to extract it:

import __future__
import ast
import sys

print('Python version:', sys.version_info)

sys_t = sys.version_info[:3]

s = '__future__ import {} {} for you; the version: {} vs. your version: {}'

for name in __future__.all_feature_names:
    optional, mandatory, _ = ast.literal_eval(str(getattr(__future__, name)).lstrip('_Featur'))
    optional, mandatory = optional[:3], mandatory[:3]
    print('\nName: {}'.format(name))
    tmp = [None, None, optional, sys_t]
    if optional <= sys_t:
        tmp[:2] = 'is', 'included'
    else:
        tmp[:2] = 'not', 'included'
    print(s.format(*tmp))
    tmp[2] = mandatory
    if mandatory <= sys_t:
        tmp[:2] = 'is', 'fixed'
    else:
        tmp[:2] = 'not', 'fixed'
    print(s.format(*tmp))

On my system this outputs:

Python version: sys.version_info(major=3, minor=7, micro=1, releaselevel='final', serial=0)

Name: nested_scopes
__future__ import is included for you; the version: (2, 1, 0) vs. your version: (3, 7, 1)
__future__ import is fixed for you; the version: (2, 2, 0) vs. your version: (3, 7, 1)

Name: generators
__future__ import is included for you; the version: (2, 2, 0) vs. your version: (3, 7, 1)
__future__ import is fixed for you; the version: (2, 3, 0) vs. your version: (3, 7, 1)

Name: division
__future__ import is included for you; the version: (2, 2, 0) vs. your version: (3, 7, 1)
__future__ import is fixed for you; the version: (3, 0, 0) vs. your version: (3, 7, 1)

Name: absolute_import
__future__ import is included for you; the version: (2, 5, 0) vs. your version: (3, 7, 1)
__future__ import is fixed for you; the version: (3, 0, 0) vs. your version: (3, 7, 1)

Name: with_statement
__future__ import is included for you; the version: (2, 5, 0) vs. your version: (3, 7, 1)
__future__ import is fixed for you; the version: (2, 6, 0) vs. your version: (3, 7, 1)

Name: print_function
__future__ import is included for you; the version: (2, 6, 0) vs. your version: (3, 7, 1)
__future__ import is fixed for you; the version: (3, 0, 0) vs. your version: (3, 7, 1)

Name: unicode_literals
__future__ import is included for you; the version: (2, 6, 0) vs. your version: (3, 7, 1)
__future__ import is fixed for you; the version: (3, 0, 0) vs. your version: (3, 7, 1)

Name: barry_as_FLUFL
__future__ import is included for you; the version: (3, 1, 0) vs. your version: (3, 7, 1)
__future__ import not fixed for you; the version: (3, 9, 0) vs. your version: (3, 7, 1)

Name: generator_stop
__future__ import is included for you; the version: (3, 5, 0) vs. your version: (3, 7, 1)
__future__ import is fixed for you; the version: (3, 7, 0) vs. your version: (3, 7, 1)

Name: annotations
__future__ import is included for you; the version: (3, 7, 0) vs. your version: (3, 7, 1)
__future__ import not fixed for you; the version: (4, 0, 0) vs. your version: (3, 7, 1)

When Python >= 3.8 introduces __future__ imports (there are none yet as I write this), removing these and running on Python 3.7 obviously would impact the functionality.

like image 36
Chris_Rands Avatar answered Oct 14 '22 04:10

Chris_Rands