从Python Interpreter

时间:2017-07-13 18:06:50

标签: python python-import

我正在使用Flask blueprints功能创建模块化应用。结果,我的目录结构如下:

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

这里的模块目录不会与Python模块混淆,它们用于为我的项目提供模块化结构(核心模块,foo模块,条形模块等)。现在,模块目录中的每个文件夹(以及其中包含相同名称的模块,例如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

有解决方法吗?那么,我可以在代码和解释器中成功导入db模块吗?

2 个答案:

答案 0 :(得分:2)

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

Python 2.X import models的默认行为是先查找相对,然后查找绝对搜索路径顺序。因此,它应该可以工作。

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

如果您想了解有关导入python模块的更多信息,建议您使用以下关键字开始研究:模块搜索路径 python包导入相对包导入

答案 1 :(得分:1)

我知道我参加聚会迟到了,但是我想我找到了解决这个问题的方法。希望这对从事大型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)