我有一个问题,我想从两个不同的文件中使用git(gitpython)repo。但是,我无法想出一种只能克隆一次的智能方法,然后在模块之间共享对象。回购非常大,所以每当我需要访问对象时克隆它们都不是最佳的。
我尝试在名为utils.py
的文件中创建一个类及其实例。但是,当导入它们时,似乎并没有克隆repos,即使它应该发生在__init__
中类的utils.py
中。当然,这必须是一些Python保护措施,以防止挂在进口上。
我已经尝试过子类化dict并在访问时使用__getattr__
进行克隆,如果它还没有,但它没有工作。它似乎只是导入但是像以前一样跳过了克隆。
这是我需要在utils.py
中定义的内容,以便我可以将其导入其他地方:
compiler_repo = git.Repo.clone_from(someurl, somepath)
答案 0 :(得分:1)
init 中的代码只是与其他代码一样运行的python代码。如果你在其中放入无限循环或阻塞等待,那么导入确实可以挂起。
您可以通过将昂贵的初始化代码放在应用程序调用的函数中来最小化库的启动时间。它不会改变要完成的工作量,但至少工作的时间是在应用程序的控制之下,并且更容易弄清楚出现了什么问题(失败 init 代码很难调试。
有多种方法可以隐藏初始化步骤。例如,您可以使用延迟加载器定义类:
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时阻塞。