簡體   English   中英

添加彼此依賴的python模塊作為git子模塊

[英]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)適用於此)。

(我自己想通了)
這可以通過刪除子模塊庫的文件夾引入的額外間接來解決。 您需要RepoARepo當前為空的__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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM