1

From this post:

Python: Disabling relative import

it is indicated that relative import can be disabled by:

from __future__ import absolute_import

However this rule seems cannot be extended to Jupyter notebook. Here is a quick experiment, when I create a python file that has identical name with a python package (in this case networkx). It can cause all absolute import of that package to fail. The following is a screenshot that describe this case:

enter image description here

The installed package 'network' already contains the submodule 'drawing', yet the import failed with the following message:

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-2-e38c4f8fc4a0> in <module>
      1 from __future__ import absolute_import
      2 
----> 3 from networkx import drawing

ImportError: cannot import name 'drawing'

How to fix it in Jupyter notebook or Jupyter lab? Does this means there is no way I can avoid relative import?

UPDATE: thanks a lot for the answers, one of them is to suggest that I have a corrupted PYTHONPATH (or sys.path), this is not the case, I have added the following line to show the inconsistency of PYTHONPATH and resolved module path:

from __future__ import absolute_import
import os
import sys


for p in sys.path:
    print(p)

print("=================")

import networkx
print(os.path.abspath(networkx.__file__))

from networkx import drawing

result:

> /home/shared/anaconda3/lib/python36.zip
> /home/shared/anaconda3/lib/python3.6
> /home/shared/anaconda3/lib/python3.6/lib-dynload
> /home/peng/.local/lib/python3.6/site-packages
> /home/shared/anaconda3/lib/python3.6/site-packages
> /home/shared/anaconda3/lib/python3.6/site-packages/IPython/extensions
> /home/peng/.ipython
> ================= /home/peng/git/convnet-abstraction/slide/package/networkx.py
> --------------------------------------------------------------------------- ImportError                               Traceback (most recent call
> last) <ipython-input-4-d28ac292787c> in <module>
>      12 print(os.path.abspath(networkx.__file__))
>      13 
> ---> 14 from networkx import drawing
> 
> ImportError: cannot import name 'drawing'

Here is another screenshot:

enter image description here

tribbloid
  • 4,026
  • 14
  • 64
  • 103
  • 1
    This isn't what relative imports are. That _is_ an absolute import, but absolute imports are always relative to `sys.path`, and `sys.path` contains `"."`, the current directory – Eric Jan 19 '19 at 22:46
  • I know it's kind of abusing the terminology, but in this case networkx is indeed perceived by Jupyter lab as referring to the networkx.py in the relative path. So how should I call this phenomenon? – tribbloid Jan 19 '19 at 23:00
  • 1
    Also, assuming that "Python 3" in the corner is accurate, implicit relative imports are already disabled by default, and `from __future__ import absolute_import` doesn't change the import behavior. (`from __future__ import absolute_import` only disables implicit relative imports, which aren't supported at all on Python 3. It does nothing to explicit relative imports or absolute imports you might mistake for relative imports.) – user2357112 Jan 19 '19 at 23:23
  • I suspect you're running into something [like this](https://github.com/asottile/scratch/wiki/PythonPathSadness) – anthony sottile Jan 20 '19 at 02:02
  • I think your update is incorrect. The first entry on the path is almost certainly `""`, which `print(p)` will show as a blank line. I reckon you ignored that output when you pasted it here. – Eric Jan 20 '19 at 07:39
  • @Eric thanks a lot! you are right, let me try if I can remove that from path – tribbloid Jan 20 '19 at 22:03

1 Answers1

2

Relative imports are not relevant here. What's happening is sys.path probably looks something like:

[
 '',  # the current directory
 'C:\\Program Files\\Python 3.5\\python35.zip',
 'C:\\Program Files\\Python 3.5\\DLLs',
 'C:\\Program Files\\Python 3.5\\lib',
 'C:\\Program Files\\Python 3.5', 
 #network x is in one of these two
 'C:\\Users\\<you>\\AppData\\Roaming\\Python\\Python35\\site-packages',
 'C:\\Program Files\\Python 3.5\\lib\\site-packages'
]

When you type import networkx, it goes through each of these directories in order looking for either networkx.py. It find the one in your "Untitled folder" first.

The best way to fix this is to rename your file, or put it in a sub-directory, mystuff/networkx

It would be a bad idea, but you could also do sys.path.remove('') to remove the first entry.

Eric
  • 95,302
  • 53
  • 242
  • 374