简体   繁体   English

如何将目录导入为python模块

[英]how to import a directory as python module

if there is a directory /home/project/aaa . 如果存在目录/home/project/aaa and I know that it is a Python package. 而且我知道这是一个Python包。

so, how can i import this module by just knowing its path. 因此,我如何仅通过知道其路径来导入该模块。

means that, i hope that code is worked: 意味着,我希望代码能够正常工作:

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

the only way i knew is that, adding /home/project to sys.path 我知道的唯一方法是,将/home/project添加到sys.path

but it maybe incur some problem: 但这可能会引起一些问题:

if i add /home/project to sys.path 如果我将/home/project添加到sys.path

and if there a dir pytest in path /home/project . 以及是否在目录/home/project有dir pytest

then the official pytest package would not work. 那么官方的pytest软件包将无法正常工作。

i try importlib yet. 我尝试importlib了。 but it seems that importlib can just import a file as a module, not a path. 但似乎importlib只能将文件作为模块而不是路径导入。

so, i try it: 所以,我尝试一下:

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

or 要么

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

both of them are not work. 他们两个都不工作。

so, is there any other way to do what i want? 所以,还有其他方法可以做我想要的吗?

oh, i am using Python3.6 哦,我在用Python3.6


UPDATED AT 20170628 于20170628更新

(NOTICE: there is a __init__.py in folder /home/project/aaa ) (注意: /home/project/aaa文件夹中有一个__init__.py

all solutions i known is that import module from a single file. 我知道的所有解决方案都是从单个文件导入模块。

if there is bbb.py file in folder /home/project/aaa 如果文件夹/home/project/aaabbb.py文件

then, add /home/project/aaa to sys.path or __path__ (whatever) 然后,将/home/project/aaa添加到sys.path__path__ (无论如何)

import bbb is worked, but not the import aaa import bbb是可行的,但不能import aaa

what i wanna ask is how to import folder (or directory) as a module. 我想问的是如何将文件夹(或目录)作为模块导入。

for my example, folder aaa is consided as a module. 在我的示例中,文件夹aaa被视为一个模块。

i wanna use import aaa not import {SOMETHING IN AAA} 我想使用import aaa而不是import {SOMETHING IN AAA}

Here are five different ways of how to accomplish that task. 这是完成任务的五种不同方式。

For the following considerations I refer to Python 3.5+. 出于以下考虑,我指的是Python 3.5+。


Register a custom Finder 注册自定义Finder

Python uses finders for when importing modules. 导入模块时,Python使用查找器 If a finder knows how to deal with a particular requested module then it returns a corresponding module spec and otherwise None . 如果查找程序知道如何处理特定的请求模块,则它将返回相应的模块规范 ,否则返回None Python has three different finders already registered which can be found in sys.meta_path : 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'>]

The first one handles built-in modules, the second one frozen modules (some kind of "self-contained" Python scripts, see the wiki ) and the last one handles everything which can be found on sys.path . 第一个处理内置模块,第二个处理冻结模块(某种“自包含” Python脚本,请参见wiki ),最后一个处理所有可在sys.path上找到的内容。 So if we modified sys.path by appending '/home/project' then it would be this finder which provides the corresponding spec. 因此,如果我们通过添加'/home/project'修改sys.path ,那么它将是提供相应规范的finder。

Instead of modifying sys.path we can register our own finder which uses the functionality of PathFinder : 无需修改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)

Here we explicitly tell the PathFinder to look into the /home/project when importing modules. 在这里,我们明确地告诉PathFinder导入模块时要查看/home/project

We can register the finder as follows: 我们可以按以下方式注册查找程序:

import sys
sys.meta_path.append(CustomFinder)

Then we can import the package aaa which will be found by the CustomFinder : 然后,我们可以导入包aaa ,这将由CustomFinder找到:

import aaa

For more information see PEP-302 . 有关更多信息,请参阅PEP-302

Extend sys.path 扩展系统sys.path

We can modify sys.path in order to put the required package on the path: 我们可以修改sys.path以便将所需的软件包放在路径上:

import sys

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

Appending this directory to the path won't block "existing" (eg built-in packages) with the same name due to the order of searching that is performed during an import. 将此目录附加到路径不会由于导入期间执行的搜索顺序而阻止具有相同名称的“现有”(例如,内置软件包)。

Add a local module containing a __path__ 添加包含__path__的本地模块

You can add a local module aaa.py (in fact you can add it to any location which is on the Python path) which contains the following code: 您可以添加包含以下代码的本地模块aaa.py (实际上您可以将其添加到Python路径上的任何位置):

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

Then you can perform import statements which will refer to the package that you referred to with the __path__ variable: 然后,您可以执行import语句,该语句将引用使用__path__变量引用的包:

from aaa import whatever

If you want to import aaa you can mimic this by applying the same method one level up in the directory hierarchy. 如果要import aaa ,则可以通过在目录层次结构中上一级应用相同的方法来模仿。 Add a local module project.py (for example) with the following code: 使用以下代码添加本地模块project.py (例如):

__path__ = ['/home/project']

Then you can do 那你可以做

from project import aaa

which is very much similar import aaa if aaa was on the path (provided that no other module named project has precedence on the path). 如果aaa在路径上,则与import aaa非常相似(前提是没有其他名为project模块在路径上具有优先级)。

Create a symlink pointing to the package 创建指向软件包的符号链接

You can create a symlink that points to the package's directory. 您可以创建一个指向程序包目录的符号链接。 For example on Unix: 例如在Unix上:

ln -s /home/project/aaa aaa

Then you can import the package via import aaa , given you're executing this in the directory where you placed the symlink. 然后,可以在import aaa符号链接的目录中执行此操作,然后通过import aaa导入软件包。

The symlink can also be created within your program via 也可以在程序中通过以下方式创建符号链接

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)

Install the package via setuptools 通过setuptools安装软件包

You can add a /home/project/setup.py script which contains (for example) the following code: 您可以添加/home/project/setup.py脚本,该脚本包含(例如)以下代码:

from setuptools import setup

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

Then you can install the package via cd /home && pip install -e project and you can readily import it in your other Python files: 然后,您可以通过cd /home && pip install -e project安装该软件包,然后可以将其轻松导入其他Python文件中:

import aaa
from aaa import whatever

By using virtualenv you can keep your installed packages in a clean state. 通过使用virtualenv ,可以使已安装的软件包保持干净状态。

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

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