[英]add python modules that depend on each other as git submodules
我在2個獨立的git存儲庫中有這兩個小模塊:
RepoA/A.py
def foo():
return "Hello World"
RepoB/B.py
import sys
try:
import A
except ImportError:
print("Dependency not available!")
sys.exit(1)
def bar():
return A.foo() + " EXTENDED!"
您會看到B
當前假設A
可全局導入(安裝或在腳本執行目錄中)。
兩者在其根目錄中都有一個空的__init__py
,以使它們可以作為子模塊導入。
現在我有另一個更大的存儲庫C需要B.它有A和B兩個可用作git子模塊,所以結構實際上如下所示:
RepoC
|---utils/
| |---__init__.py
| |---RepoA/
| | |---__init__.py
| | |---A.py
| |---RepoB/
| |---__init__.py
| |---B.py
|---C.py
RepoC/C.py
import utils.B
print(B.bar())
RepoC/utils/__init__.py
# remove the 1-layer indirection through the submodule
from .RepoB import B
現在打印Dependency not available!
正如預期的那樣,因為A
不是全局可用的,而是在B
位置永遠無法猜測的位置(在這種情況下,它需要from ..RepoA import A
)。 如果我通過將其添加到sys.path
再次使A
全局可用它將工作:
RepoC/utils/__init__.py
import os, sys
import inspect
def fake_install(module_path):
# the submitted module path is relative to the caller's location
# therefore get that script's file location first
caller_module = inspect.getmodule(inspect.stack()[1][0])
caller_dir = caller_module.__file__.rsplit(os.path.sep, 1)[0]
# build an absolute file path and append it to the system paths
path = os.path.join(os.path.abspath(caller_dir), *module_path.split("."))
sys.path.append(path)
fake_install("RepoA")
# remove the 1-layer indirection through the submodule
from .RepoB import B
這感覺就像一個可怕的解決方案。
另一個想法是根本不使用git子模塊,而只是在requirements.txt中收集依賴關系作為git-links,編寫一些setup.exe腳本並讓pip 實際安裝它們。
我怎樣才能優雅地克服這個問題? 是否有任何導入技巧可以讓我這樣做?
您可能已經猜到了,我認為您有兩種選擇:要么讓A和B成為C的一部分,要么制作B和C獨立包。
這是pip的工作“把一個放在sys.path中的某個地方”,所以你不妨讓他這樣做而不是自己動手。 您可以在需求中使用git鏈接,但不能在setup.py中使用git鏈接,因此如果您有更多依賴項(D需要B需要C)並且您無法在PyPI上發布這些依賴項,那么您可能需要一個私有PyPI服務器(devpi)適用於此)。
(我自己想通了)
這可以通過刪除子模塊庫的文件夾引入的額外間接來解決。 您需要RepoA
和Repo
當前為空的__init__.py
文件作為其包含模塊(此處為utils
),以使RepoC
能夠在其中使用依賴項。
編輯您的RepoB/__init__.py
,如下所示:
from .. import *
然后通過將其添加到utils的__init__.py
,使您的utilA中的依賴項A
可用:
from .RepoA import A
現在您需要做的就是在本地B.py
進行導入:
from . import A
您也可以將其作為全局依賴項運行:
try:
from . import A
except ImportError:
import A
現在,所有庫的用戶必須做的是:
為了使這種方法更通用,我希望子模塊的根目錄中的所有__init__.py
都像這樣的橋接:
RepoA/__init__.py
from .. import *
__all__ = ["A"]
RepoB/__init__.py
from .. import *
__all__ = ["B"]
並做同樣的事情,即從另一方面去除間接。 在本例中,在utils/__init__.py
:
from .RepoA import *
from .RepoB import *
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.