比方说,我有以下目录结构:
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
。
该计划失败,说b
当它不存在c_file.py
尝试导入abd
。 (它确实不存在的,因为我们是在进口它的中间。)
如何解决这个问题加以解决呢?
如果依赖于C和C取决于,不是他们实际上是相同的单位呢?
你真的应该考虑为什么你有分裂的A和C到两个包,因为无论你有一些代码,您应该分裂成另一个包(以使它们都依赖于新的包装,而不是对方),或者你应该把它们合并在一个封装中。
您可能会推迟进口,例如a/__init__.py
:
def my_function():
from a.b.c import Blah
return Blah()
也就是说,推迟进口,直到真正需要它。 不过,我也有我的包定义/用途仔细看,像一个循环依赖指出可能表明一个设计问题。
我想知道,这几次(通常同时与需要知道对方的机型交易)。 简单的解决办法就是导入整个模块,然后引用你所需要的东西。
因此,而不是做
from models import Student
于一体,并
from models import Classroom
在其他的,只是做
import models
在其中的一个,然后调用models.Classroom当你需要它。
问题是,从一个目录中运行时,默认情况下只有那些子目录的包作为候选进口可见的,所以你不能导入ABD但是,您可以导入BD因为B的一个子包。
如果你真的想要导入ABD在c/__init__.py
,你可以通过改变系统路径为高于一个目录下即可,改变进口的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 a.b.c
当你想运行在C模块,脚本,另外一个困难出现。 在这里,包A和B是不存在的。 你能砍的__int__.py
在c目录移到sys.path指向顶级目录,然后导入__init__
在C内任何模块,以便能够使用完整路径导入ABD我怀疑这是很好的做法进口__init__.py
,但它已经为我的使用情况。
我建议以下模式。 使用它可以让自动完成和类型提示的正常工作。
cyclic_import_a.py
import playground.cyclic_import_b
class A(object):
def __init__(self):
pass
def print_a(self):
print('a')
if __name__ == '__main__':
a = A()
a.print_a()
b = playground.cyclic_import_b.B(a)
b.print_b()
cyclic_import_b.py
import playground.cyclic_import_a
class B(object):
def __init__(self, a):
self.a: playground.cyclic_import_a.A = a
def print_b(self):
print('b1-----------------')
self.a.print_a()
print('b2-----------------')
使用此语法您不能导入A和B级
from playgroud.cyclic_import_a import A
from playground.cyclic_import_b import B
你不能在B类声明参数的类型__ __的init方法,但你可以“投”这样说:
def __init__(self, a):
self.a: playground.cyclic_import_a.A = a
另一种方法是使用代理服务器的d_file。
例如,假设您想与C_FILE共享等等类。 因此,d_file包含:
class blah:
def __init__(self):
print("blah")
以下是你在c_file.py输入:
# 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()
而在一个的init的.py:
from b.c import c_file
from b.d 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()