Нужно ли размещать __init__.py в каждом каталоге в дереве каталогов, ведущем к моему классу? - PullRequest
4 голосов
/ 17 апреля 2020

Я строю Django проект с Python 3.6. Я создал эту структуру каталогов ...

project
- manage.py
- scripts
  - run_commands.py
- commons
  - util
    - __init__.py
    - my_class.py

Содержимое init .py:

from . import my_class

В другом классе я пытаюсь импортировать мой MyClass вот так

from commons.util import MyClass

но я получаю эту ошибку

ModuleNotFoundError: No module named 'commons'

Правильно ли я создаю init .py?

Ответы [ 2 ]

2 голосов
/ 21 апреля 2020

Похоже, проблема в том, что MyClass не находится в commons.util, потому что вы импортировали только модуль с именем my_class, а не сам класс.

Вместо этого файл commons/util/__init__.py должен содержит следующий импорт:

from .my_class import MyClass

Я не думаю, что это решит вашу проблему, потому что вы получите ошибку, отличную от показанной, но вы получите ошибки для это в конечном итоге.

Обновление

Во-первых, я бы рекомендовал прочитать этот ответ для хорошего объяснения того, как импорт работает в python.

Обычно при выполнении from commons.util import MyClass интерпретатор сканирует содержимое sys.path для модуля с именем commons.
Я предполагаю, что вы не установили sys.path для включения папки проекта следовательно, ModuleNotFoundError.

TLDR; у вас есть 2 варианта:

  • Вручную установите sys.path в run_commands.py для проверки папки вашего проекта (не делайте этого!)
  • Используйте Django Command класс

Чтобы использовать Django класс Command, вам необходимо настроить папку вашего проекта следующим образом:

project
- manage.py
- commons
- management
  - commands
    run_commands.py     
  - util
    - __init__.py
    - my_class.py

Теперь в 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)

Вы можете выполнить новую команду следующим образом:

python3 manage.py run_commands
0 голосов
/ 17 апреля 2020

Раньше было так, что да, вам нужно поместить __init__.py в каждый каталог, который будет обрабатываться как модуль python, так как без __init__.py python не заглянет внутрь этого каталог для импортируемого кода.

- project
  - __init__.py
  - commons
    - __init__.py
    - util
      - __init__.py
      - my_class.py

Но так как Восстановить Монику указывает ниже, это больше не верно для Python 3.3 + . Таким образом, в зависимости от вашей версии Python вам потребуется принять обоснованное решение.

Обратите внимание, что вам может потребоваться или не потребоваться __init__.py в каталоге root project (если вам нужно их вообще), это зависит, если у него есть определения, которые являются частью исходного дерева. Но он вам не понадобится, если это просто контейнер, как вы видите, например, в том, как организовано большинство Django проектов.

https://docs.python.org/3/tutorial/modules.html. https://docs.python.org/3/tutorial/modules.html#packages

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...