Python import substitution is different between 3.4.6 and 3.5.2

The shadows for Python imports seem to differ between versions 3.4.6 and 3.5.2:

$ cat time.py from time import time $ pyenv global 3.4.6 $ python -V Python 3.4.6 $ python time.py Traceback (most recent call last): File "time.py", line 1, in <module> from time import time File "/home/vagrant/tmp/time.py", line 1, in <module> from time import time ImportError: cannot import name 'time' $ pyenv global 3.5.2 $ python -V Python 3.5.2 $ python time.py $ echo no error no error 

Question 1: Why ... these things?

Question 2: Is there anything in the change summary about this? I can’t find anything ...

+7
python import python-internals shadowing
source share
1 answer

The documentation states that

When a module named spam imported, the interpreter first searches for the built-in module with this name . If it is not found, it then searches for a file named spam.py in the list of directories specified by the sys.path variable.

(my accent)

time not a built-in module module in Python 3.4, but this was changed in Python 3.5:

 me@temp :~$ python3.4 -c 'import sys; print("time" in sys.builtin_module_names)' False me@temp :~$ python3.5 -c 'import sys; print("time" in sys.builtin_module_names)' True 

You can see the patch in which the change was made here (referring to number 5309 ). Given that issue 5309 is mentioned in the change log, nothing is said. module time , it is safe to say that the change was a side effect and is a detail of the implementation of CPython.

Since time not a built-in module in CPython 3.4, and the first directory in sys.path is the current script, from time import time tries to import the time attribute from your time.py file, but fails and throws ImportError .

CPython 3.5 time has a built-in module. According to the quote above, starting from time import time successfully imports the built-in module without searching for modules on sys.path .

Both versions of CPython will cause the same error if you obscure a non-built-in module from the standard library, for example inspect :

 me@temp :~$ cat inspect.py from inspect import signature me@temp :~$ python3.4 -c 'import inspect' Traceback (most recent call last): File "<string>", line 1, in <module> File "/home/me/inspect.py", line 1, in <module> from inspect import signature ImportError: cannot import name 'signature' me@temp :~$ python3.5 -c 'import inspect' Traceback (most recent call last): File "<string>", line 1, in <module> File "/home/me/inspect.py", line 1, in <module> from inspect import signature ImportError: cannot import name 'signature' 
+6
source share

All Articles