1

I have a very simple project architecture:

project/
  __init__.py
  dira/
    __init__.py
    a.py
  dirb/
    __init__.py
    b.py

All the __init__.py are empty. a.py only contains a "hello" function:

def hello(): return "hello world"

I want b.py to use the hello function from a.py.

What I tried so far:

Following answers from this question, I tried:

import ..dira.a as aa
aa.hello

But when running b.py I get a syntax error on ..a.a

I also tried to manually add the project directory to sys.path and then run:

import dira.a as aa
aa.hello

But when running b.py I get:

ImportError: No module named 'a'

What should I do? Why the solution I found doesn't work?

Anne Aunyme
  • 506
  • 4
  • 14

1 Answers1

0

Short answer: import ..dira is invalid syntax and only from ..dira.a import hello works Working configuration: b.py:

from ..dira.a import hello
print(hello())

Also, from docs:

"Note that relative imports are based on the name of the current module. Since the name of the main module is always "main", modules intended for use as the main module of a Python application must always use absolute imports."

So if you do relative imports you cannot call b.py directly. Apperently, you cannot do it from project level either. (Python interpreter in project folder, call import dirb.b)

An error occurs:
    ValueError: attempted relative import beyond top-level package

But calling import project.dirb.b makes proper output:

hello world

EDIT: Why import project.dirb.b can be called only outside of project module?

Let's look at the problem from interpreter's side.

  1. You call import project.dirb.b. It runs dirb/init.py, 'current module' is project.dirb
  2. Interpreter finds command from ..dira.a import hello
  3. It treats double dot ..dira.a as "move one module up and go to dira and import a.hello". 'Current module' is project.dirb, so parent module is project, thus it finds parent.dira
  4. What happens when you call import dirb.b directly? It fails on trying to go level up in module hierarchy and reports error.

Thus, relative import makes project.dirb.b importable only outside of project.

R2RT
  • 2,061
  • 15
  • 25
  • Thanks for the remark about the syntax, but it still raises an exception: `SystemError: Parent module '' not loaded, cannot perform relative import` (which corresponds to your answer). I also tried to replace `import dirb.b` by `import project.dirb.b` but it raises `ImportError: No module named 'project'`. – Anne Aunyme Oct 24 '17 at 13:57
  • What is working directory of your python? `os.getcwd()`. What I mean is when you use relative import you can import your `b` module only from console started outside of your project. – R2RT Oct 24 '17 at 14:30
  • All the tests I made are launched from `project/`. Do you mean I have to go one level higher? – Anne Aunyme Oct 24 '17 at 14:36
  • Go one level higher or drop design, where bound modules are not hierarchized. If b is dependent on a, maybe it is reasonable to make b submodule of a? – R2RT Oct 24 '17 at 14:39
  • dira/ is supposed to contain a package with several functions that don't depend on anything. I also want to have dirb/ and dirc/, two other different packages independent from each other that both use dira/ functions. I can put everything in the same directory (that's what I currently do), but as the project grows it becomes harder and harder to read, and I though packaging would help making it clearer. – Anne Aunyme Oct 24 '17 at 14:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/157390/discussion-between-anne-aunyme-and-r2rt). – Anne Aunyme Oct 24 '17 at 14:47