Python包导入错误导入错误:没有已知父包的相对导入尝试

发布于 2025-01-12 01:53:27 字数 455 浏览 0 评论 0原文

该项目具有与图片相同的结构:我试图从“index.py”中的“mod.py”导入

from .. import mod

但是,它给出错误:“ImportError:尝试相对导入,没有已知的父包”如果您使用此选项:

from pack1 import mod

然后错误:“ModuleNotFoundError错误:没有名为'pack1'的模块”

输入图像描述这里

PROJECT/
  pack1/
    __init__.py
    mod.py
  pack2/
    __init__.py
    index.py

有什么问题吗?

The project has the same structure as in the picture: I'm trying to import from "mod.py " in "index.py "

from .. import mod

However, it gives the error: "ImportError: attempted relative import with no known parent package" If you use this option:

from pack1 import mod

Then error: "ModuleNotFoundError error: there is no module named 'pack1'"

enter image description here

PROJECT/
  pack1/
    __init__.py
    mod.py
  pack2/
    __init__.py
    index.py

What is the problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

遮云壑 2025-01-19 01:53:27

这是 StackOverflow 上反复出现的问题。 (在我看来)大部分的困惑来自于 Python 解释它所看到的文件和文件夹的方式是基于 Python 运行的位置。首先,一些术语:

  • 模块:包含Python代码的文件。
  • package:包含Python代码文件和其他文件夹的文件夹。

当你在一个目录(文件夹)中启动Python时,它不“知道”该目录的命名空间应该是什么。即,如果您在启动 Python 时在 Z:\path\to_my\project\ 中工作:

  1. 认为 project 是一个包裹。
  2. 您想要从中导入的任何 .py 文件都将作为模块位于其自己的命名空间中。
  3. 您想要从中导入的任何文件夹也将作为包位于其自己的命名空间中。
  • __init__.py 怎么样?从 3.3 版本开始,Python 具有隐式命名空间包,允许导入而无需创建空的 __init__.py 文件。

考虑#2:如果你有两个文件:first.pysecond.py

path/
  to_my/
    project/
      >>Python is running here<<
      first.py
      second.py

包含这些内容:

# first.py
first_var = 'hello'
# second.py
from .first import first_var

second_var = first_var + ' world'

如果你尝试像这样导入:

>>> import second

Python基本上会执行以下操作:

  • “好的,我看到了 secondary.py”
  • “将其作为模块读取,酋长!”
  • "好的,它要导入 .first
  • ". 表示获取包含 first.py 的包(文件夹)" "
  • 等等,我没有 first.py 的父包!”
  • “最好提出错误。”

相同的规则也适用于 #3。如果我们向项目中添加一些包,如下所示

path/
  to_my/
    project/
      >>Python is running here<<
      first.py
      second.py
      pack1/
        mod.py
        other_mod.py
      pack2/
        index.py

:以下内容:

# pack1/mod.py
mod_var = 1234
# pack1/other_mod.py
from .mod import mod_var

other_var = mod_var * 10
# pack2/index.py

from ..pack1 import mod

当您尝试像这样导入时:

>>> from pack2 import index.py

导入pack2/index.py 也会因为 second.py 的原因而失败,Python 会像这样沿着导入链向上移动:

  • “Reading in < code>index.py 作为一个模块。"
  • "看起来它想从 ..pack1 导入 mod
  • “好的,.index.pypack2父包命名空间,发现了。”
  • “所以,..pack2 的父包。”
  • “但是,我没有 pack2 的父包!”
  • “最好提出错误。”

我们如何让它发挥作用?两件事。

首先,将 Python 的运行位置上移一级,以便所有 .py 文件和子文件夹都被视为同一包命名空间的一部分,这允许文件使用相对引用相互引用。

path/
  to_my/
    >>Python is running here now<<
    project/
      first.py
      second.py
      pack1/
        mod.py
        other_mod.py
      pack2/
        index.py

因此,现在 Python 将 project 视为包命名空间,并且其中的所有文件都可以使用该级别的相对引用。

这会改变您在 Python 解释器中导入的方式:

>>> from project.pack2 import index.py

其次,您可以进行显式引用而不是相对引用。这可能会使导入语句变得非常长,但如果您有几个需要相互拉取的顶级模块,那么您可以这样做。当您在一个文件中定义函数并在另一个文件中编写脚本时,这非常有用。

# first.py
first_var = 'hello'
# second.py
from first import first_var  # we dropped the dot

second_var = first_var + ' world'

我希望这有助于消除有关相对进口的一些困惑。

This is a recurring question on StackOverflow. And much of the confusion (in my opinion) comes from how Python interprets the files and folders it sees is based on where Python is run from. First, some terminology:

  • module: a file containing Python code.
  • package: a folder containing files with Python code and other folders.

When you start Python in a directory (folder), it doesn't "know" what the namespace of that directory should be. I.e., if you are working in Z:\path\to_my\project\ when you start Python:

  1. it does NOT consider project to be a package.
  2. any .py files you want to import from will be in their own namespace as modules.
  3. any folders you want to import from will also be in their own namespace as packages.
  • What about __init__.py? Since version 3.3, Python has implicit namespace packages, which allows importing without needing to create an empty __init__.py file.

Consider #2: if you have two files: first.py and second.py:

path/
  to_my/
    project/
      >>Python is running here<<
      first.py
      second.py

with these contents:

# first.py
first_var = 'hello'
# second.py
from .first import first_var

second_var = first_var + ' world'

if you try to import like this:

>>> import second

Python basically does the following:

  • "ok, I see second.py"
  • "Reading that in as a module, chief!"
  • "Ok, it wants to import .first
  • "The . means get the package (folder) that contains first.py"
  • "Wait, I don't have a parent package for first.py!"
  • "Better raise an error."

The same rules apply for #3 as well. If we add a few packages to the project like this:

path/
  to_my/
    project/
      >>Python is running here<<
      first.py
      second.py
      pack1/
        mod.py
        other_mod.py
      pack2/
        index.py

with the following contents:

# pack1/mod.py
mod_var = 1234
# pack1/other_mod.py
from .mod import mod_var

other_var = mod_var * 10
# pack2/index.py

from ..pack1 import mod

and when you try to import like this:

>>> from pack2 import index.py

The import in pack2/index.py is going to fail for the same reason second.py, Python will work its way up the import chain of dots like this:

  • "Reading in in index.py as a module."
  • "Looks like it wants to import mod from ..pack1.
  • "Ok, . is the pack2 parent package namespace of index.py, found that."
  • "So, .. is the parent package of pack2."
  • "But, I don't have a parent package for pack2!"
  • "Better raise an error."

How do we make it work? Two thing.

First, move where Python is running up one level so that all of the .py files and subfolders are considered to be part of the same package namespace, which allows the file to reference each other using relative references.

path/
  to_my/
    >>Python is running here now<<
    project/
      first.py
      second.py
      pack1/
        mod.py
        other_mod.py
      pack2/
        index.py

So now Python sees project as a package namespace, and all of the files within can use relative references up to that level.

This changes how you import when you are in the Python interpreter:

>>> from project.pack2 import index.py

Second, you make explicit references instead of relative references. That can make the import statements really long, but if you have several top-level modules that need to pull from one another, this is how you can do it. This is useful when you are defining your functions in one file and writing your script in another.

# first.py
first_var = 'hello'
# second.py
from first import first_var  # we dropped the dot

second_var = first_var + ' world'

I hope this helps clear up some of the confusion about relative imports.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文