Reputation: 943
I'm building a Django project with Python 3.6. I have created this directory structure ...
project
- manage.py
- scripts
- run_commands.py
- commons
- util
- __init__.py
- my_class.py
The contents of init.py are
from . import my_class
In another class, I attempt to import my MyClass like this
from commons.util import MyClass
but I'm getting this error
ModuleNotFoundError: No module named 'commons'
Am I creating my init.py properly?
Upvotes: 5
Views: 2187
Reputation: 1730
It used to be the case that yes, you need to put an __init__.py
in every directory that is going to be treated as a python module as without an __init__.py
python wouldn't look inside that directory for importable code.
- project
- __init__.py
- commons
- __init__.py
- util
- __init__.py
- my_class.py
But as Reinstate Monica points out below this is no longer true as of Python 3.3+. So, depending on your version of Python you will need to make an informed decision.
Note, you might or might not need an __init__.py
in the root project
directory (if you need them at all), it depends if it has definitions that are part of the source tree. But you won't need it if it's just a container, like you see in the way most Django projects are organised, for example.
Upvotes: 2
Reputation: 16032
It looks like the problem is that MyClass
is not located in commons.util
, because you only imported the module named my_class
, not the class itself.
Instead the file commons/util/__init__.py
should contain the following import:
from .my_class import MyClass
I don't think this will solve your problem, because you would be getting a different error than the one shown, but you will get errors for this eventually.
First, I'd recommend reading this answer for a good explanation for how imports work in python.
Basically, when you execute from commons.util import MyClass
, the interpreter scans the contents of sys.path
for a module named commons
.
I assume you didn't set sys.path
to include your project folder, hence the ModuleNotFoundError
.
TLDR; you have 2 options:
sys.path
in run_commands.py
to check your project folder (Don't do this!)Command
classTo use Django's Command
class, you will need to adjust your project folder similar to the following:
project
- manage.py
- commons
- management
- commands
run_commands.py
- util
- __init__.py
- my_class.py
Now in run_commands.py:
from django.core.management.base import BaseCommand
from commons.util import MyClass
class Command(BaseCommand):
def handle(*args, **options):
print("handling", MyClass)
You can execute the new command with the following:
python3 manage.py run_commands
Upvotes: 4