Python中的循环导入依赖
假设我有以下目录结构:
a\ __init__.py b\ __init__.py c\ __init__.py c_file.py d\ __init__.py d_file.py
在a
包的__init__.py
, c
包被导入。 但是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()