Python import shadowing seems to be different between version 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 is... those things ?
Question 2: Is it there something in a changelog about that ? I can't find anything...
In Python, you use the import keyword to make code in one module available in another. Imports in Python are important for structuring your code effectively. Using imports properly will make you more productive, allowing you to reuse code while keeping your projects maintainable.
Python caches all imported modules This all happened because Python caches modules. In Python, every module that is imported is stored in a dictionary called sys.
This is caused by the fact that the version of Python you're running your script with is not configured to search for modules where you've installed them. This happens when you use the wrong installation of pip to install packages.
So there's four different ways to import: Import the whole module using its original name: pycon import random. Import specific things from the module: pycon from random import choice, randint. Import the whole module and rename it, usually using a shorter variable name: pycon import pandas as pd.
The documentation states that
When a module named
spam
is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file namedspam.py
in a list of directories given by the variablesys.path
.
(emphasis mine)
time
wasn't a built-in module module in Python 3.4, but that 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 that introduced the change here (related to issue 5309). Considering that the changelog mentions the issue 5309, but doesn't say anything re. the time
module, it's safe to say that the change was a side-effect and is an implementation detail of CPython.
Since time
isn't a built-in module in CPython 3.4, and the first directory in sys.path
is the current script directory, from time import time
attempts to import the time
attribute from your time.py
file, but fails and throws the ImportError
.
In CPython 3.5 time
is a built-in module. As per the quote above, running from time import time
successfully imports the built-in module, without searching for modules on sys.path
.
Both CPython versions will raise the same error if you shadow a non-builtin module from the standard library, such as 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'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With