8

I have been googling this for the past hours and can't find an equivalent question anywhere. Also the documentation for 2.7 and 3.5 seem identical, so I don't think this behavior is documented.

Here is my directory structure:

project
    -- project.py
    -- api
        -- __init__.py
        -- subapi
            -- __init__.py

contents of project/project.py: import api

contents of project/api/__init__.py: import subapi

If I execute python project.py (using python 2.7) from inside the projects folder, it returns without an error. If I do the same with python 3 (python3 project.py), then it crashes with

Traceback (most recent call last):
  File "project.py", line 1, in <module>
    import api
  File "/home/me/Documents/project/api/__init__.py", line 1, in <module>
    import subapi
ImportError: No module named 'subapi'

If I rewrite the import statement to use paths relative to the projects directory (import api.subapi), then it works with python 2 as well as 3. It's not a satisfying solution though because that requires me to reference parent modules from within sub modules which kind of defeats the idea of modularity..

Does anyone have an idea what I can do to get the behavior of python2 back? The module search algorithm should prioritize searching in the local directory of the file using the import statement. It should also prioritize these files above built in modules by the way. Try importing a module 'test'..

--EDIT-- I was asked by stackoverflow to differentiate my question from another called "How to do relative imports". I think this question is different because I am asking specifically about differences between two versions. Using relative imports is the solution, not the question.

Philon
  • 143
  • 2
  • 11
  • 2
    Try using relative paths i.e. `import .subapi` – Marandil Feb 02 '17 at 20:37
  • Possible duplicate of [How to do relative imports in Python?](http://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python) – Mad Physicist Feb 02 '17 at 20:42
  • This absolutely is documented, but I can see how the documentation might be hard to find/read for a beginner. – Mad Physicist Feb 02 '17 at 20:43
  • It is documented, but not super easy to find. Imports in Python 3 are more explicit: https://wiki.python.org/moin/PortingPythonToPy3k#relative-imports http://stackoverflow.com/a/34462008/554546 –  Feb 02 '17 at 20:44
  • @Marandil: I don't think that works; [PEP 328](https://www.python.org/dev/peps/pep-0328/#guido-s-decision) says explicit relative imports have to use `from` syntax. – user2357112 Feb 02 '17 at 20:45

1 Answers1

6

Use an explicit relative import:

from . import subapi
user2357112
  • 260,549
  • 28
  • 431
  • 505
  • 1
    works! I still am confused why they opted to change the importing behavior in python 3. Maybe they want to force people to use a flat module hierarchy (unlike nodejs) – Philon Feb 02 '17 at 20:43
  • @Phil. Absolutely not. They actually made it easier to write nested libraries. – Mad Physicist Feb 02 '17 at 20:48
  • @user2357112 thanks for that link. I quote: "it is proposed that all import statements be absolute by default (searching sys.path only) with special syntax (leading dots) for accessing package-relative imports" – Philon Feb 02 '17 at 21:59