从 Python 解释器运行时获取"ImportError: attempted relative import with no known parent package"



我正在使用 Flask 蓝图功能创建一个模块化应用程序。结果,我的目录结构是这样的:

project
__init__.py
config.py
mould.py
modules
__init__.py
core
__init__.py
core.py
db.py
models.py

这里的模块目录不要与 Python 模块混淆,它们用于为我的项目(核心模块、foo 模块、bar 模块等(提供模块化结构。现在,模块目录中的每个文件夹(以及其中具有相同名称的模块,例如core.core(都通过执行以下操作动态导入到我的主烧瓶应用程序(mould.py(中:

for item in os.listdir("modules"):
if not os.path.isfile("modules" + os.sep + item) and not item.startswith("__"):
ppath = "modules" + "." + item
fullpath = "modules" + "." + item + "." + item
module = importlib.import_module(fullpath)
app.register_blueprint(module.app)
print("Registered: " + ppath)

因此,我无法在模块脚本中执行此操作,例如db.py

import models

由于当整个模块在项目级别执行时,它会给出路径错误,所以我不得不这样做:

from . import models

这解决了问题,我能够成功导入所有模块。但是,当我转到核心模块目录进行一些故障排除并启动python解释器时,它不允许我导入db模块:

>>> import db
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "db.py", line 7, in <module>
from . import models
ImportError: attempted relative import with no known parent package

有没有办法解决这个问题?那么,我可以在代码和解释器中成功导入数据库模块吗?

我知道我来晚了,但我想我已经找到了解决这个问题的方法。 希望这对从事大型Python项目的其他人有用。

诀窍是尝试一种导入格式,如果第一种格式失败,则回退到另一种格式。

方法1

db.py

try:
# Assume we're a sub-module in a package.
from . import models
except ImportError:
# Apparently no higher-level package has been imported, fall back to a local import.
import models

从好的方面来说,这种方法非常简单,但不能很好地扩展(模块名称重复(。 可以通过以编程方式导入来改进缩放。

方法 2(不推荐(

db.py

import importlib
root = 'project.modules.core'
my_modules = ['core', 'models']
for m in my_modules
try:
globals()[m] = importlib.import_module(root + '.' + m)
except ImportError:
globals()[m] = importlib.import_module(m)

globals(( 是全局符号表。

当然,现在这个功能需要在每个模块中复制。 我不确定这实际上是对第一种方法的改进。 但是,您可以将此逻辑分离到它自己的独立包中,该包位于pythonpath上的某个位置。

方法3

package_importer.py

import importlib
def import_module(global_vars, root, modules):
for m in modules
try:
global_vars[m] = importlib.import_module(root + '.' + m)
except ImportError:
global_vars[m] = importlib.import_module(m)

db.py

import package_importer
root = 'project.modules.core'
my_modules = ['core', 'models']
package_importer.import_module(globals(), root, my_modules)

这可能有点过时了,但也许其他人会从我的答案中受益。由于 python2 和 python3 具有不同的默认导入行为,因此您必须在这两个 python 版本之间确定。

Python 2.Ximport models的默认行为是先查找相对路径顺序,然后查找绝对搜索路径顺序。因此,它应该有效。

但是,在Python 3.X中,import models的默认行为是仅在绝对路径中查找模型(称为绝对导入(。当前包核心被跳过,并且由于模块dbsys.path搜索路径中的其他任何地方都找不到,因此它会引发错误。要解决此问题,您必须使用带有点的 import 语句from . import models以明确您正在尝试从相对目录导入。

如果你有兴趣了解更多关于导入python模块的信息,我建议你从以下关键词开始你的研究:模块搜索路径,python包导入和相对包导入

最新更新