0

(Originally asked on r/learnpython, but figured I'd ask here too.)

Since this problem came up while dealing with django, I'll explain in that context.

So I have a django project folder, and some internal django apps living in that project folder, like this:

project_module
├ apps
│ ├ app_module1
│ │ ├ models.py
│ │ └ ...
│ ├ app_module2
│ └ ...
├ settings.py
└ ...

now the app_modules are available as project_module.apps.app_module1 and so on, but since there won't be anything colliding with the app names in project_module, I'd like to drop the .apps part so I can just refer to them as project_module.app_module1 and such, consistently.

So, I create __init__.py everywhere, and put this into project_module/__init__.py:

from .apps import app_module1

And this sort of works, since I can import project_module.app_module1 and it seems to work.

BUT, Django internally uses importlib.import_module here and there, and in those cases I encounter ModuleNotFoundError: No module named 'project_module.app_module1'. In those cases I can use the .apps again, but this sort of breaks consistency.

A bit of experiment later, I'm convinced import_module ignores re-exports from __init__.py; But why does this happen, and is there a way I can play around this in this case?

Miles
  • 100
  • 1
  • 10
  • "And this sort of works, since I can `import project_module.app_module1` and it seems to work." - are you sure? That shouldn't actually work. You would need to do `from project_module import app_module1`. – user2357112 May 02 '20 at 10:38
  • 1
    If you want to drop the `.apps` part, why not just *actually eliminate* the `apps` subpackage and move the contents into `project_module`? – user2357112 May 02 '20 at 10:41
  • @user2357112 Hmm, you're right, I can't `import project_module.app_module1`. I must have confused it with something else, my bad. As for removing `apps` subpackage, I certainly could do that, but I'd also like to keep apps in their own directory because... it feels more organized that way? I dunno. – Miles May 02 '20 at 10:55
  • So I'm guessing that importing (and re-exporting) a module makes it an attribute of current module or something like that, but not its actual submodule. That'd mean I can't fiddle with module structure via imports in `__init__.py`; But then, is there a way to fiddle with it at all? – Miles May 02 '20 at 11:12

1 Answers1

0

So, I create init.py everywhere, and put this into project_module/init.py

Consider adding project_module/apps to PYTHONPATH or sys.path if you're really determined to remove app from imports. That's also a hack in this use-case, but more predictable.

RafalS
  • 5,834
  • 1
  • 20
  • 25