【问题标题】:Do I need to place __init__.py in each directory in a directory tree leading to my class?我是否需要将 __init__.py 放在通向我的班级的目录树中的每个目录中?
【发布时间】:2020-07-31 04:03:33
【问题描述】:

我正在使用 Python 3.6 构建一个 Django 项目。我已经创建了这个目录结构...

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?

【问题讨论】:

  • 您尝试从哪个模块导入MyClass?你能展示一下它的目录结构吗?
  • @ReinstateMonica,目录结构已更新。我正在尝试使用“run_commands.py”文件中的导入。

标签: django python-3.x import module


【解决方案1】:

问题似乎是MyClass 不在commons.util 中,因为您只导入了名为my_class 的模块,而不是类本身。

文件commons/util/__init__.py 应该包含以下导入:

from .my_class import MyClass

我认为这不会解决您的问题,因为您会遇到与所示错误不同的错误,但您最终会遇到此错误。

更新

首先,我建议阅读this answer 以获得关于导入如何在 python 中工作的一个很好的解释。

基本上,当您执行from commons.util import MyClass 时,解释器会扫描sys.path 的内容以查找名为commons 的模块。
我假设您没有设置 sys.path 以包含您的项目文件夹,因此 ModuleNotFoundError

TLDR;你有两个选择:

  • run_commands.py 中手动设置sys.path 以检查您的项目文件夹(不要这样做!)
  • 使用 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

【讨论】:

  • 感谢您的帮助。我首先运行“source venv/bin/activate”来激活我的虚拟环境,然后运行“python scripts/run_commands.py myarg1 myarg2”。我确实尝试按照您的建议编辑 init.py 文件,但正如您预测的那样,发生了同样的错误。
【解决方案2】:

过去的情况是,您需要在每个将被视为 python 模块的目录中放置一个__init__.py,因为没有__init__.py,python 不会在该目录中查找可导入代码.

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

但正如Reinstate Monica 在下面指出的那样,这是no longer true as of Python 3.3+。因此,根据您的 Python 版本,您需要做出明智的决定。

注意,您可能需要也可能不需要根 project 目录中的 __init__.py(如果您需要它们),这取决于它是否具有属于源代码树一部分的定义。但如果它只是一个容器,你就不需要它,就像你在大多数 Django 项目的组织方式中看到的那样。

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

【讨论】:

  • 谢谢。是否需要将任何内容放入 commons 目录中的 init.py 文件中?
  • 不,只是为了使模块可导入,它们都可以是空的。
  • 谢谢。奇怪的是,我仍然收到空文件的“ModuleNotFoundError: No module named 'commons'”错误。我什至尝试将 util 目录中的“init.py”文件设为空。
  • 使用空的 __init__.py 文件,您需要完整地限定导入,例如:from commons.util.my_class import MyClass 但看到错误是从 commons 触发的,我怀疑您的 Django 项目配置错误无论如何__init__.py 的情况。如果你没有使用startproject,你应该从头开始。 docs.djangoproject.com/en/3.0/intro/tutorial01/…
  • 从 python 3.3+ 开始,这根本不是真的。 related
猜你喜欢
  • 2017-11-22
  • 1970-01-01
  • 2011-08-07
  • 2014-06-16
  • 1970-01-01
  • 2012-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多