2017-06-27 679 views
1

如果有目錄/home/project/aaa。 ,我知道它是一個Python包。如何導入目錄爲python模塊

那麼,我怎麼才能通過知道它的路徑導入這個模塊。

意味着,我希望代碼工作:

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

我知道的唯一辦法是,增加/home/projectsys.path

但它可能招致一些問題:

如果我加/home/projectsys.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

(注意:有文件夾/home/project/aaa一個__init__.py

我知道所有的解決方案是,進口模塊來自單個文件。

如果bbb.py文件夾/home/project/aaa

再向其中加入/home/project/aaasys.path__path__(任何)

import bbb的工作,但不是import aaa

什麼我想要問的是如何作爲模塊導入文件夾(或目錄)

對於我的例子,文件夾aaa被認爲是一個模塊。

我想用import aaaimport {SOMETHING IN AAA}

+0

LMGTFY:https://askubuntu.com/questions/470982/how-to-add-a-python-module-to-syspath/471168 –

+0

@EgorBiriukov:提問者已經知道如何添加一個目錄到sys .path',他們已經給出了一個很好的理由來需要不同的選擇。 – user2357112

回答

1

下面是如何完成這個任務五種不同的方法。

對於以下考慮,我指的是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'>] 

第一個處理的內置模塊,第二個冷凍模塊(某種「自足」的Python腳本,請參閱the wiki)最後一個處理所有可以在sys.path上找到的東西。所以如果我們通過追加'/home/project'來修改sys.path那麼它就是這個發現者提供的相應規範。

不是修改sys.path我們可以註冊自己的取景器,它使用的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() 

這個目錄追加到路徑將不會阻止「現有」(如內置包)由於在導入過程中執行的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安裝包裝,您可以隨時將其導入您的其他Pyt hon文件:

import aaa 
from aaa import whatever 

通過使用virtualenv您可以保持您的安裝包處於乾淨狀態。

+0

'/ home/project/aaa'是一個目錄,而不是單個文件。 –

+0

@KilerdChan我更新了我的答案以澄清。所有這三種方法都適用於你的場景('aaa'是一個目錄)。修改'sys.path'可能是最簡單的一個。我認爲通過'setuptools'&'pip'安裝軟件包是最乾淨的方法。你在你的問題中提到你擔心修改現有的sys.path陰影(例如內置的包),但它不會因[搜索順序](https://docs.python.org/3/引用/ import.html#搜索)。如果你_append_到'sys.path',那麼添加的位置的優先級最低。 –

+0

謝謝你這樣詳細的答案。我試圖弄清楚如何編輯我從github克隆的項目,這是失蹤的作品! – vorpal