Python 从父包导入

Python import from parent package

我在 Python 中遇到一些导入问题。

这是一个简单的错误示例。

我有这样的目录结构:

app
|---__init__.py
|---sub_app
    |---__init__.py

代码:

app/__init__.py

shared_data = {
    'data': 123
}

from sub_app import more_shared_data
print more_shared_data

app/sub_app/__init__.py

more_shared_data = {
    'data': '12345'
}
from app import shared_data
print shared_data

但是我收到错误:

ImportError: No module named app

如何将 shared_data 字典导入 app/sub_app/__init__.py?

您可以为此使用 relative imports。例子-

在你的 app/sub_app/__init__.py -

more_shared_data = {
    'data': '12345'
}
from .. import shared_data
print shared_data

这应该适用于您提供的简单示例,但它确实会导致循环导入,app 正在导入 sub_app 并且 sub_app 正在导入 app

对于更复杂的用例,您可能会在定义特定元素之前遇到错误(如果您导入 sub_app),然后在 sub_app/__init__.py 中您尝试导入应用程序并使用那些元素仅在 sub_app 的导入语句之后定义。一个非常简单的例子,它会导致问题 -

app/__init__.py -

from .sub_app import more_shared_data
print(more_shared_data)

shared_data = {
    'data': 123
}

app/sub_app/__init__.py -

more_shared_data = {
    'data': '12345'
}
from .. import shared_data
print(shared_data)

现在,如果您尝试导入 app ,您将收到错误 -

>>> import app
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<some file>\__init__.py", line 1, in <module>
    from .shared import more_shared_data
  File "<some file>\sub_app\__init__.py", line 4, in <module>
    from .. import shared_data
ImportError: cannot import name 'shared_data'

你应该重新考虑 shared_data 是否属于 app/__init__.py ,或者它可以移动到 sub_app/__init__.py 然后从那里导入 app

你这里有几个问题,其中一个是隐藏的。

看起来您正在尝试调用您的程序:

python app/__init__.py
python app/sub_app/__init__.py

这会导致问题,因为主文件的目录被认为是程序的根目录。也就是为什么sub_app看不到app.

您可以像这样调用您的程序

python -m app.sub_app

这样python假设当前目录是根目录,在这个目录下寻找模块app.sub_app。这会导致另一个问题。为了能够 运行 包,您需要在包中提供 __main__.py(以及 __init__.py)。如果模块不相互导入,那么调用顺序将是app/__init__.pyapp/sub_app/__init__.py,然后是app/sub_app/__main__.py

app
|---__init__.py
|---sub_app
    |---__init__.py
    |---__main__.py

app/sub_app/__main__.py 可以做如下事情:

from app import shared_data
from . import more_shared_data
# or
from app.sub_app import more_shared_data

最后,隐藏的问题是你有循环导入。也就是说,app 依赖于 sub_appsub_app 依赖于 appappsub_app 都需要先加载另一个,然后才能加载——这当然是不可能的。您应该重构代码以避免循环导入。