Python中的循环导入依赖

假设我有以下目录结构:

a\ __init__.py b\ __init__.py c\ __init__.py c_file.py d\ __init__.py d_file.py 

a包的__init__.pyc包被导入。 但是c_file.py导入abd

程序失败,当c_file.py尝试导入abd时,说b不存在。 (而且它确实不存在,因为我们正在导入它。)

这个问题怎么解决?

如果一个取决于c和c取决于一个,他们不是实际上是同一个单位呢?

你应该仔细研究为什么你把a和c分成两个包,因为你有一些代码需要拆分到另一个包中(为了使它们都依赖于新的包而不是彼此),或者你应该合并它们整合成一个包装

您可以推迟导入,例如在a/__init__.py

 def my_function(): from abc import Blah return Blah() 

那就是推迟import,直到真正需要。 不过,我也会仔细看看我的包装定义/用途,因为像指出的那样的循环依赖可能表明devise问题。

我很想知道这个过程(通常在处理需要彼此了解的模型时)。 简单的解决scheme就是导入整个模块,然后引用你需要的东西。

所以,而不是做

 from models import Student 

在一个,和

 from models import Classroom 

在另一方面,只是做

 import models 

在其中一个,然后调用模型。当你需要它的时候。

问题是,从目录运行时,默认情况下只有子目录的包是可见的候选导入,所以你不能导入ABD然而,你可以导入BD因为B是一个子包。

如果你真的想在c/__init__.py导入abd,你可以通过将系统path改为a上面的一个目录来实现,并将a/__init__.py中的导入改为导入abc

你的a/__init__.py应该是这样的:

 import sys import os # set sytem path to be directory above so that a can be a # package namespace DIRECTORY_SCRIPT = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0,DIRECTORY_SCRIPT+"/..") import abc 

当你想在脚本中运行c中的模块时会产生一个额外的困难。 这里包a和b不存在。 你可以破解c目录中的__int__.py ,将sys.path指向顶层目录,然后在c中的任何模块中导入__init__ ,以便能够使用完整的path导入abd我怀疑这是好的做法导入__init__.py但它已经为我的用例工作。

另一个解决scheme是使用d_file的代理。

例如,假设你想和c_file共享blah类。 d_file因此包含:

 class blah: def __init__(self): print("blah") 

这是你在c_file.py中input的内容:

 # do not import the d_file ! # instead, use a place holder for the proxy of d_file # it will be set by a's __init__.py after imports are done d_file = None def c_blah(): # a function that calls d_file's blah d_file.blah() 

在a的init .py中:

 from bc import c_file from bd import d_file class Proxy(object): # module proxy pass d_file_proxy = Proxy() # now you need to explicitly list the class(es) exposed by d_file d_file_proxy.blah = d_file.blah # finally, share the proxy with c_file c_file.d_file = d_file_proxy # c_file is now able to call d_file.blah c_file.c_blah()