繁体   English   中英

如何将目录导入为python模块

[英]how to import a directory as python module

如果存在目录/home/project/aaa 而且我知道这是一个Python包。

因此,我如何仅通过知道其路径来导入该模块。

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

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

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

但这可能会引起一些问题:

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

以及是否在目录/home/project有dir pytest

那么官方的pytest软件包将无法正常工作。

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

所以,我尝试一下:

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

要么

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

他们两个都不工作。

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

哦,我在用Python3.6


于20170628更新

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

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

如果文件夹/home/project/aaabbb.py文件

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

import bbb是可行的,但不能import aaa

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

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

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

这是完成任务的五种不同方式。

出于以下考虑,我指的是Python 3.5+。


注册自定义Finder

导入模块时,Python使用查找器 如果查找程序知道如何处理特定的请求模块,则它将返回相应的模块规范 ,否则返回None Python已经注册了三个不同的查找器,可以在sys.meta_path找到sys.meta_path

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

第一个处理内置模块,第二个处理冻结模块(某种“自包含” Python脚本,请参见wiki ),最后一个处理所有可在sys.path上找到的内容。 因此,如果我们通过添加'/home/project'修改sys.path ,那么它将是提供相应规范的finder。

无需修改sys.path我们可以注册使用PathFinder功能的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

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

将此目录附加到路径不会由于导入期间执行的搜索顺序而阻止具有相同名称的“现有”(例如,内置软件包)。

添加包含__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

如果aaa在路径上,则与import aaa非常相似(前提是没有其他名为project模块在路径上具有优先级)。

创建指向软件包的符号链接

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

ln -s /home/project/aaa aaa

然后,可以在import 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 ,可以使已安装的软件包保持干净状态。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM