首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用python库从相对路径动态import_module

如何使用python库从相对路径动态import_module
EN

Stack Overflow用户
提问于 2022-05-26 16:39:31
回答 2查看 1.8K关注 0票数 0

我的文件夹结构看起来如下:

代码语言:javascript
复制
__init__.py
core/
    fields.py
    managers.py
    models.py
    __init__.py
models/
    products.py
    suppliers.py
    __init__.py

fields.py中的A类中,我试图使用importlib.load_module加载类供应商,而products.py或suppliers.py是从后者中定义的。这是填充一些配置以生成一些sql所必需的。

下面的方法生成TypeError: the 'package' argument is required to perform a relative import for '..models.suppliers.Supplier''。我不知道如何定义包,因为这不是一个已安装的包。

代码语言:javascript
复制
import importlib

model_name = "Supplier"
path = f"...models.{model_name.lower()}s.{model_name}"
model = importlib.import_module(path)

为了解决这个问题,我尝试了以下各种组合,但都没有效果。根据..的组合错误ModuleNotFoundError: No module named '.core'ModuleNotFoundError: No module named '.models'。我在吸毒。

代码语言:javascript
复制
import importlib

model_name = "Supplier"
path = f"...models.{model_name.lower()}s.{model_name}"
model = importlib.import_module(path, package=".core.fields")
代码语言:javascript
复制
path = f"{model_name.lower()}s"
model = importlib.import_module(path, package="..models")

它也不起作用--但显然导入from ..models import Supplier是有效的。

我还尝试让python使用绝对路径。但是通过使用这种方法,错误变成:ImportError: attempted relative import with no known parent package (引用suppliers.py中的导入)。

在这种情况下,suppliers.py中使用的相对导入似乎失败了。见下面的例子。

代码语言:javascript
复制
from importlib.machinery import SourceFileLoader
from pathlib import Path
import os

model_name = "Supplier"
parent_path = Path(__file__).resolve().parent.parent
module_path = os.path.join(parent_path, 'models', f'{model_name.lower()}s.py')
Model = getattr(SourceFileLoader(model, module_path).load_module(), model_name)

编辑:为了完整性,抛出ModuleNotFoundError: No module named '.'。所以也拒绝了。

代码语言:javascript
复制
model = __import__(f"..models.{model.lower()}.{model}")

我遗漏了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-05-26 18:00:04

再读一遍之后,解决方案就直直地盯着我。

您可以使用getattr,而不是尝试使用导入库来做有趣的事情。

代码语言:javascript
复制
def find_my_class(class_name):
    from .. import models as configuration_models

    module = getattr(configuration_models, f"{class_name.lower()}s")
    return getattr(module, class_name)
票数 0
EN

Stack Overflow用户

发布于 2022-05-26 17:33:33

下面是文档中关于如何加载给定模块文件路径的模块的配方:https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly

代码语言:javascript
复制
...
import importlib

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)

不使用路径库:

(我之所以保留这一点,是因为文件名操作和dir处理的示例仍然需要,即使在遵循上面的菜谱时也是如此)

实际上,在Python中导入给定文件路径的文件的正确方法是复杂的。无需搜索另一个菜谱,以下是一种临时修补sys.path的方法,并调用普通__import__从指定的dir获取文件。

( Python文件的路径应该使用文件系统符号:/分隔符,而不是.。此代码将忽略文件扩展名)

代码语言:javascript
复制
import sys
from pathlib import Path

def importpath(path):
    strpath = str(path)
    if not strpath.startswith("/"):
        parent_path = Path(sys._getframe().f_globals.get("__file__", ".")).parent
        path = parent_path / path
    else:
        path = Path(path)
    try:
        sys.path.insert(0, str(path.parent))
        module = __import__(path.stem)
    finally:
        sys.path.pop(0)
    return module

但是,这段代码将导入给定的文件,作为一个惟一的Python模块,而不知道它应该在哪个包中。这意味着,如果该模块中存在任何相对导入,则它们将失败。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72395188

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档