如何将目录导入为python模块

时间:2017-06-27 17:19:21

标签: python python-3.x python-import

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

所以,我怎么能通过知道它的路径来导入这个模块。

意味着,我希望代码能够运作:

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

我知道的唯一方法就是将/home/project添加到sys.path

但可能会出现一些问题:

如果我将/home/project添加到sys.path

如果路径pytest中有目录/home/project

然后官方pytest包不起作用。

我还试试importlib。 但似乎importlib只能将文件作为模块导入,而不是路径。

所以,我试试看:

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

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

它们都不起作用。

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

哦,我正在使用Python3.6

20170628更新

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

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

如果文件夹bbb.py

中有/home/project/aaa个文件

然后,将/home/project/aaa添加到sys.path__path__(无论如何)

import bbb已成功,但不是import aaa

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

对于我的示例,文件夹aaa被视为一个模块。

我想使用import aaa而不是import {SOMETHING IN AAA}

1 个答案:

答案 0 :(得分:2)

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

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

注册自定义Finder

Python在导入模块时使用finders。如果查找程序知道如何处理特定的请求模块,那么它将返回相应的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'>]

第一个处理内置模块,第二个处理冻结模块(某种&#34;自包含&#34; Python脚本,请参阅the wiki),最后一个处理所有可能的模块在sys.path找到。因此,如果我们通过附加sys.path来修改'/home/project',则可以使用此查找程序提供相应的规范。

我们可以注册使用PathFinder功能的自己的查找器,而不是修改sys.path

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

扩展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()

将此目录添加到路径中不会阻止&#34;现有&#34; (例如,内置包)由于导入期间执行的order of 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在路径上,则

非常相似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

安装软件包

您可以添加/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,您可以将已安装的软件包保持在干净状态。