4

I am new to Python packages, and I am struggling to get something working. I have 3 packages : engine, ui and db. I'd like db to be used from the other two packages. What is the correct way to do so?

I'd like not to install the db package, since I am currently developing the 3 packages at the same time.

Thanks!


For the moment, I am trying to do so with imports of sibling packages, but it sucks so much that I'm not sure this is the correct way to do so. This question is closely related to tons of questions such as Relative imports in Python 3 or ValueError: attempted relative import beyond top-level package, but none of them has a valid, working answer for me :-(

Here's what I have so far:

src/
  __init__.py     # empty file (is it useful?)
  db/
    __init__.py   # empty file
    constants.py
  ui/
    __init__.py   # empty file
    index.py
  engine/
    ...some stuff...

Here is index.py:

from .. import db
print(db.constants.stuff)

However, running cd ui && python3 index.py or python3 -m index.py fail with SystemError: Parent module '' not loaded, cannot perform relative import

When I tweak this project, I sometimes get yet other errors, such as ValueError: Attempted relative import in non-package

From what I read on https://docs.python.org/3/tutorial/modules.html, this should work, shouldn't it?

What am I doing wrong? What should I do to (do such a simple thing as) use a common package from two other packages?

Daladim
  • 198
  • 10
  • Can you share the entire project structure using something like `tree`? Because the current info only shows one actual file per package. Perhaps you are confusing packages and modules? – Arunmozhi Oct 19 '17 at 07:04
  • This is the actual, current structure (`engine` is currently empty but will eventually need stuff from `db`). So yes, I have currently one module per package. But packages will soon grow – Daladim Oct 19 '17 at 07:26

1 Answers1

0

__init__.py is useful, even though it's empty. It tells python that a folder is a python package.

I think what you need is to modify the system path. For example, say you want to import constants.py into index.py, index.py would look like this:

import sys
sys.path.append("..")
from db import constants
ConorSheehan1
  • 1,640
  • 1
  • 18
  • 30
  • This works, thank a lot! However, how dirty is this workaround? I thought I read that this is terribly dirty so I did not want to try this (but heck, this works, this is all I want after fiddling with these imports for hours) – Daladim Oct 19 '17 at 18:00
  • Also, I know empty `__init__.py` are fine, but I was wondering how useful was the top-level one. It works without it, but maybe defining a top-level package is a good practise? – Daladim Oct 19 '17 at 18:08
  • All it does is append the folder above the current one the script is in to your path, so that you can import sibling modules. I'm not sure whether it counts as dirty or not, that's kind of up to interpretation. That said, it might be a good idea to change your project structure to avoid sibling imports. Could you have a source directory which contains all your classes and functions, and then have index.py one level up which imports everything and runs some main function? – ConorSheehan1 Oct 20 '17 at 08:09
  • As far as the top level \_\_init\_\_.py goes, if you ever need to import this structure into something else as a package, you'll need it. Is the top level meant to be a python package, or a project containing other packages? – ConorSheehan1 Oct 20 '17 at 08:17
  • It is only meant to be a project. I'm pretty sure I'll never use it as a package. So I guess I could safely drop this file then. Thanks! – Daladim Oct 20 '17 at 10:37