【问题标题】:Python - import a module directory given full pathPython - 导入给定完整​​路径的模块目录
【发布时间】:2016-11-20 08:24:00
【问题描述】:

我在这里有一个 python 模块/root/python/foo.py。我在文件夹/root/lib/ 中有一堆其他模块,看起来像这样


    lib/
    |
    ├─ module1/
    |  ├─ __init__.py
    |  └─ bar.py
    |
    └─ module2/
       ├─ __init__.py
       └─ bar.py

我想从foo.py 导入/root/lib/module1/root/lib/module2。我想必须将/root/lib/ 添加到python 系统路径。 This stack overflow answer 告诉您如何使用imp.load_sourceimportlib.machinery.SourceFileLoaderimportlib.util 类从文件加载模块(取决于python 版本)。我认为这些仅在模块是单个文件时才有效。如果我在 Python 3.4 中尝试这样的事情

from importlib.machinery import SourceFileLoader
problem_module = SourceFileLoader('test_mod', '/root/lib/module1').load_module()

我收到了IsADirectoryError

我的问题是,如果模块是一个目录,是否有类似的方法来加载模块(给定它的完整路径),而不将整个 lib/ 文件夹添加到系统路径?

【问题讨论】:

  • 在module1之后添加'
  • 您需要使用sys.path 来可靠地导入模块。见this question
  • "我希望不必将 /root/lib/ 添加到 python 系统路径。" - 为什么不?这是到目前为止实现这一目标的最简单方法。
  • 我不想将目录添加到系统路径,因为我认为库中可能有数百个模块,并且我认为只针对我想要的文件夹会更好。可能将lib文件夹添加到系统路径并没有我想象的那么糟糕。

标签: python


【解决方案1】:

Python 并没有为我们提供一种简单的方法来加载 sys.path 无法引用的文件,最常见的解决方案是执行以下操作之一:

  1. 将所需路径添加到sys.path
  2. 重组你的模块,使正确的路径已经在sys.path

几乎所有其他解决方案都不能解决问题(使用非预期的方法来完成工作),有些可能会让人头疼。

然而,python 确实为我们提供了一种机制,让我们可以模拟分布在 sys.path 上未保存的文件夹中的包,您可以通过模块中的 specifying a __path__ special name 来做到这一点:

__path__ = ["/root/lib"]

将此行放在一个名为 lib.py 的文件中,并将其放在与 foo.py 相同的文件夹中,以便由它导入(因此在您的情况下为 root/python/),然后从 foo.py 中导入,您可以这样做期望:

import lib.module1
#or
from lib import module1

这向 python 表明 .module1 子包位于指定的 __path__ 的某个位置,并将使用预期的导入机制从该目录(或多个目录)加载并保持您的 sys.path 不变。

【讨论】:

  • 我认为你是对的,我可能只需要最终将 lib 文件夹添加到 system.path。但如果这是正确的方法,那么我想知道为什么 python 允许你导入一个模块,如果它只是一个使用 SourceFileLoader 的文件(在 python 3.4 中)。如果他们有这个功能,你会认为它是文件还是目录都没关系。
  • 读取名称...Source File Loader,您没有指定文件,并加载单个源模块并不像整个导入机制那么简单,所以我不会指望它在任何情况下都能 100% 工作。
  • 是的,我只是想知道为什么没有SourceDirectoryLoader 方法,而有SourceFileLoader。但我想你是对的,它并不像只使用导入机制那么简单。
  • @pspencer 我刚刚找到了一个使用预期机制的实际解决方案,我认为这正是您所需要的。
  • @Tadhq McDonald-Jensen 您所说的解决方案是您在上面对__path__ 特殊名称所做的编辑吗?这是 python 的一个非常有趣的特性,我不知道,但它正是我正在寻找的。我一直在寻找像 SourceFileLoader 这样的方法,但是对于目录。我认为我从这个讨论中决定的是,除了将 lib 目录添加到系统路径之外,没有一种好的 Python 方式来做我想做的事情。
【解决方案2】:

试试:

from importlib.machinery import SourceFileLoader
problem_module = SourceFileLoader('test_mod', '/root/lib/module1/__init__.py').load_module()

__init__.py 应该注意同一包中的模块:

添加from . import bar 使bar.py 成为包的一部分。

一些更正:

  • module1 是一个包不是一个模块。
  • bar.py 是包module1 的模块部分

【讨论】:

  • 那种工作。我想使用 module1 作为模块名称,例如加载后,我还想从 module1 导入 bar.py。仅针对 init.py 并没有让我这样做。
  • from . import bar in __init__.py
  • 替代解决方案:from .bar import *
  • 我不想通过 init.py 文件导入 over 模块。我想做from problem_module import bar之类的事情,但我想如果我必须这样做也不会太糟糕,我只需要改变我的工作方式。
  • 这对我帮助很大,谢谢!我在尝试将文件 foo.bar.pyimportlib 解释为模块时遇到问题。foobarpy
猜你喜欢
  • 2019-10-31
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
  • 1970-01-01
相关资源
最近更新 更多