克隆 git 存储库并在别处导入对象

Clone git repository and import object elsewhere

我有一个问题,我想使用来自两个不同文件的 git (gitpython) 存储库。但是,我无法想出一个只克隆它一次,然后在模块之间共享对象的聪明方法。存储库非常大,因此每次我需要访问该对象时都克隆它们并不是最佳选择。

我已经尝试在名为 utils.py 的文件中创建 class 及其实例。但是,当我导入它们时,似乎没有克隆回购协议,即使它应该发生在 utils.py 中的 class 的 __init__ 中。当然,这一定是一些 Python 防止挂起进口的保障措施。

我已经尝试使用 subclassing dict 并在访问时使用 __getattr__ 进行克隆(如果尚未访问)但它没有用。它似乎只是导入但像以前一样跳过了克隆。

这是我需要在 utils.py 中定义的,以便我可以将其导入其他地方:

compiler_repo = git.Repo.clone_from(someurl, somepath)

init 中的代码只是 python 代码,运行 与其他代码一样。如果你在其中放置一个无限循环或阻塞等待,那么 import 确实会挂起。

您可以将昂贵的初始化代码放在应用程序调用的函数中,从而最大限度地缩短库的启动时间。它不会改变要完成的工作量,但至少工作的时间在应用程序的控制之下,并且更容易找出问题所在(失败init 代码很难调试)。

有多种方法可以隐藏初始化步骤。例如,您可以定义一个带有延迟加载器的 class:

class RepoLoader:
    def __init__(self, url, path):
        self.url = url
        self.path = path
        self._repo = None

    def fetch_repo(self):
        self._repo = git.Repo.clone_from(self.url, self.path)

    @property
    def repo(self):
        if self._repo is None:
            self.fetch_repo()
        return self._repo

compiler = RepoLoader(someurl, somepath)

您可以在包裹的其他地方使用以下方式请求回购:

from . import utils
compiler_repo = utils.compiler.repo

现在,如果包的用户想要控制它何时发生,他们可以调用 utils.compiler.fetch_repo() 作为初始化步骤,或者他们可以将其留给应用程序。通过更多的工作,您可以将 fetch_repo 放在一个单独的线程中,这样您的应用程序初始化的其余部分就可以继续进行,并且仅在代码需要 repo 时才阻塞。