如何将目录导入为 python 模块

2024-04-29

如果有目录/home/project/aaa。 我知道它是一个Python包。

那么,我如何通过知道它的路径来导入这个模块。

这意味着,我希望代码能够正常工作:

aaa = load_module("/home/project/aaa")

我知道的唯一方法是,添加/home/project to sys.path

但它可能会产生一些问题:

如果我添加/home/project to sys.path

如果有一个目录pytest在路径中/home/project.

那么官方的 pytest 包将无法工作。

i try importlib然而。 但似乎importlib只能将文件作为模块导入,而不是路径。

所以,我尝试一下:

aaa = importlib.import_module("aaa", "/home/project")

or

aaa = importlib.import_module("aaa", "/home/project/aaa")

他们俩都没有工作。

那么,还有其他方法可以做我想做的事吗?

哦,我用的是Python3.6


更新于 20170628

(注意:有一个__init__.py在文件夹中/home/project/aaa)

我知道的所有解决方案都是从单个文件导入模块。

如果有bbb.py文件夹中的文件/home/project/aaa

然后加/home/project/aaa to sys.path or __path__(任何)

import bbb是有效的,但不是import aaa

我想问的是如何导入文件夹(或目录)作为一个模块。

以我为例,文件夹aaa被视为一个模块。

我想用import aaa not import {SOMETHING IN AAA}


以下是完成该任务的五种不同方法。

出于以下考虑,我参考了 Python 3.5+。


注册定制Finder https://docs.python.org/3/library/importlib.html#importlib.abc.MetaPathFinder

Python使用finders https://docs.python.org/3/glossary.html#term-finder用于导入模块时。如果查找器知道如何处理特定请求的模块,那么它会返回相应的模块规格 https://docs.python.org/3/glossary.html#term-module-spec否则None。 Python 已经注册了三个不同的查找器,可以在sys.meta_path:

>>> import sys
>>> sys.meta_path
[<class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib_external.PathFinder'>]

第一个处理内置模块,第二个处理冻结模块(某种“独立”Python 脚本,请参阅the wiki https://wiki.python.org/moin/Freeze),最后一个处理可以在sys.path。所以如果我们修改sys.path通过附加'/home/project'那么这个查找器就会提供相应的规格。

而不是修改sys.path我们可以注册我们自己的查找器,它使用以下功能PathFinder https://docs.python.org/3/library/importlib.html#importlib.machinery.PathFinder:

import importlib.machinery

class CustomFinder(importlib.machinery.PathFinder):
    _path = ['/home/project']

    @classmethod
    def find_spec(cls, fullname, path=None, target=None):
        return super().find_spec(fullname, cls._path, target)

这里我们明确告诉PathFinder调查/home/project导入模块时。

我们可以按如下方式注册查找器:

import sys
sys.meta_path.append(CustomFinder)

然后我们就可以导入包了aaa将会发现CustomFinder:

import aaa

欲了解更多信息,请参阅PEP-302 https://www.python.org/dev/peps/pep-0302/.

Extend sys.path

我们可以修改sys.path为了将所需的包放在路径上:

import sys

sys.path.append('/home/project')
import aaa
from aaa import whatever
# Optionally remove the added path.
sys.path.pop()

将此目录附加到路径不会阻止具有相同名称的“现有”(例如内置包),因为搜索顺序 https://docs.python.org/3/reference/import.html#searching这是在导入期间执行的。

添加包含以下内容的本地模块__path__

您可以添加本地模块aaa.py(事实上​​,您可以将其添加到 Python 路径上的任何位置),其中包含以下代码:

__path__ = ['/home/project/aaa']

然后你就可以执行import语句将引用您引用的包__path__多变的:

from aaa import whatever

如果你想import aaa您可以通过在目录层次结构中应用相同的方法来模拟这一点。添加本地模块project.py(例如)使用以下代码:

__path__ = ['/home/project']

然后你可以做

from project import aaa

这非常相似import aaa if aaa位于路径上(前提是没有其他名为project在路径上具有优先权)。

创建指向包的符号链接

您可以创建一个指向包目录的符号链接。例如在 Unix 上:

ln -s /home/project/aaa aaa

然后你可以通过导入包import aaa,假设您在放置符号链接的目录中执行此操作。

符号链接也可以通过以下方式在您的程序中创建

import os

package = '/home/project/aaa'
target = os.path.split(package)[-1]  # For example.
if not os.path.exists(target):
    # `target_is_directory=True` is needed for Windows platform.
    os.symlink(package, target, target_is_directory=True)

# Now import the package.
aaa = __import__(target)

通过安装包setuptools https://pypi.python.org/pypi/setuptools

您可以添加一个/home/project/setup.py脚本包含(例如)以下代码:

from setuptools import setup

setup(
    name='aaa',
    packages=[
        'aaa',
        # Add any sub-packages that `aaa` contains here.
    ]
)

然后你可以通过安装该包cd /home && pip install -e project您可以轻松地将其导入到其他 Python 文件中:

import aaa
from aaa import whatever

通过使用virtualenv https://docs.python.org/3/library/venv.html您可以使已安装的软件包保持干净状态。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将目录导入为 python 模块 的相关文章