Forced to use inconsistent file import paths in Python (/Django)

django, import, path, python

Solution

For import to find a module, it needs to either be in sys.path. Usually, this includes "", so it searches the current directory. If you load "application" from project, it'll find it, since it's in the current directory.

Okay, that's the obvious stuff. A confusing bit is that Python remembers which modules are loaded. If you load application, then you load application2 which imports application, the module "application" is already loaded. It doesn't need to find it on disk; it just uses the one that's already loaded. On the other hand, if you didn't happen to load application yet, it'll search for it--and not find it, since it's not in the same directory as what's loading it ("."), or anywhere else in the path.

That can lead to the weird case where importing sometimes works and sometimes doesn't; it only works if it's already loaded.

If you want to be able to load these modules as just "application", then you need to arrange for project/ to be appended to sys.path.

(Relative imports sound related, but it seems like application and application2 are separate packages--relative imports are used for importing within the same package.)

Finally, be sure to consistently treat the whole thing as a package, or to consistently treat each application as their own package. Do not mix and match. If package/ is in the path (eg. sys.path includes package/..), then you can indeed do "from package.application import foo", but if you then also do "from application import foo", it's possible for Python to not realize these are the same thing--their names are different, and they're in different paths--and end up loading two distinct copies of it, which you definitely don't want.

Problem

I've recently been having some problems with my imports in Django (Python)... It's better to explain using a file diagram: ``` - project/ - application/ - file.py - application2/ - file2.py ``` In `project/application/file.py` I have the following: ``` def test_method(): return "Working" ``` The problem occurs in `project/application2/file2.py`, when I try to import the method from above: ``` from application.file import test_method ``` Usually works, but sometimes not. ``` from project.application.file import test_method ``` Does work, but it goes against Django's portability guidelines as the project folder must always be called the same. I wouldn't mind, but it's the fact that this issue is occurring inconsistently, most of the time omitting `project` is fine, but occasionally not (and as far as I can see, with no reason). I can pretty much guarantee I'm doing something stupid, but has anyone experienced this? Would I be better just putting the `project` in front of all relevant imports to keep things consistent? Honestly, it's unlikely the `project` folder name will ever change, I just want things to stick with guidelines where possible.

Original source