Python中的循环导入及其解析
我正在处理Python中循环导入的一个问题。由于解决了这个问题,我不得不更加了解Python中的包/导入 我使用的一些资源包括: 我知道这个话题已经被广泛讨论过了,我已经尽了最大的努力来熟悉这个讨论,但是我从我们的代码库中得到了一个最小的工作示例,我还没有能够使用我从上面引用的源代码中学到的技能来解决这个问题。我想征求关于这个例子的任何建议 示例的文件夹结构如下所示:Python中的循环导入及其解析,python,python-3.x,Python,Python 3.x,我正在处理Python中循环导入的一个问题。由于解决了这个问题,我不得不更加了解Python中的包/导入 我使用的一些资源包括: 我知道这个话题已经被广泛讨论过了,我已经尽了最大的努力来熟悉这个讨论,但是我从我们的代码库中得到了一个最小的工作示例,我还没有能够使用我从上面引用的源代码中学到的技能来解决这个问题。我想征求关于这个例子的任何建议 示例的文件夹结构如下所示: Source/ Package/ __init__.py A/
Source/
Package/
__init__.py
A/
__init__.py
a.py
B/
__init__.py
b1.py
b2.py
C/
__init__.py
c1.py
c2.py
每个\uuuu init\uuuu.py
都是空的。每个文件的内容如下:
Source/
Package/
__init__.py
A/
__init__.py
a.py
B/
__init__.py
b1.py
b2.py
C/
__init__.py
c1.py
c2.py
a.py
from Package.B.b1 import class_b1
from Package.B.b2 import method_b2
class class_b1(object):
def __init__(self):
pass
from Package.C.c1 import class_c1
def method_b2():
pass
import Package.C.c2 as class_c2
class class_c1(object):
def __init__(self):
pass
from Package.B.b1 import class_b1
class class_c2(object):
def __init__(self):
pass
b1.py
from Package.B.b1 import class_b1
from Package.B.b2 import method_b2
class class_b1(object):
def __init__(self):
pass
from Package.C.c1 import class_c1
def method_b2():
pass
import Package.C.c2 as class_c2
class class_c1(object):
def __init__(self):
pass
from Package.B.b1 import class_b1
class class_c2(object):
def __init__(self):
pass
b2.py
from Package.B.b1 import class_b1
from Package.B.b2 import method_b2
class class_b1(object):
def __init__(self):
pass
from Package.C.c1 import class_c1
def method_b2():
pass
import Package.C.c2 as class_c2
class class_c1(object):
def __init__(self):
pass
from Package.B.b1 import class_b1
class class_c2(object):
def __init__(self):
pass
c1.py
from Package.B.b1 import class_b1
from Package.B.b2 import method_b2
class class_b1(object):
def __init__(self):
pass
from Package.C.c1 import class_c1
def method_b2():
pass
import Package.C.c2 as class_c2
class class_c1(object):
def __init__(self):
pass
from Package.B.b1 import class_b1
class class_c2(object):
def __init__(self):
pass
c2.py
from Package.B.b1 import class_b1
from Package.B.b2 import method_b2
class class_b1(object):
def __init__(self):
pass
from Package.C.c1 import class_c1
def method_b2():
pass
import Package.C.c2 as class_c2
class class_c1(object):
def __init__(self):
pass
from Package.B.b1 import class_b1
class class_c2(object):
def __init__(self):
pass
逻辑如下。
Iexport PYTHONPATH=/path/to/Source
将包
放在sys路径中
然后我转到Package/A
并执行python A.py
a、 py从b1.py加载一个类,该类从b2.py加载一个方法,该方法从c1.py加载一个类,该类从c2.py加载一个类,该类从b1.py加载一个类(即a.py加载的同一个类)。这会导致导入错误
请注意,所有这些都是在Ubuntu 16.04中激活的Python3.6.5虚拟环境中完成的
以下是一个跟踪:
(eye_tracking) gsandh16@count:~/Documents/PythonImportTesting/MWE_refactored/Source/Package/A$ python a.py
Traceback (most recent call last):
File "a.py", line 1, in <module>
from Package.B.b1 import class_b1
File "/home/gsandh16/Documents/PythonImportTesting/MWE_refactored/Source/Package/B/b1.py", line 1, in <module>
from Package.B.b2 import method_b2
File "/home/gsandh16/Documents/PythonImportTesting/MWE_refactored/Source/Package/B/b2.py", line 1, in <module>
from Package.C.c1 import class_c1
File "/home/gsandh16/Documents/PythonImportTesting/MWE_refactored/Source/Package/C/c1.py", line 1, in <module>
import Package.C.c2 as class_c2
File "/home/gsandh16/Documents/PythonImportTesting/MWE_refactored/Source/Package/C/c2.py", line 1, in <module>
from Package.B.b1 import class_b1
ImportError: cannot import name 'class_b1'
(眼睛跟踪)gsandh16@count:~/Documents/PythonImportTesting/MWE_refactured/Source/Package/A$python A.py
回溯(最近一次呼叫最后一次):
文件“a.py”,第1行,在
从包装B.b1进口类别_b1
文件“/home/gsandh16/Documents/PythonImportTesting/MWE_refactured/Source/Package/B/b1.py”,第1行,在
从Package.B.b2导入方法_b2
文件“/home/gsandh16/Documents/PythonImportTesting/MWE_refactured/Source/Package/B/b2.py”,第1行,在
来自包装C.c1进口类别_c1
文件“/home/gsandh16/Documents/PythonImportTesting/MWE_refactured/Source/Package/C/c1.py”,第1行,在
将包C.c2作为类别_c2导入
文件“/home/gsandh16/Documents/PythonImportTesting/MWE_refactured/Source/Package/C/c2.py”,第1行,在
从包装B.b1进口类别_b1
ImportError:无法导入名称“class_b1”
我希望在不重构代码或在方法调用中插入导入的情况下(即当它们实际使用导入的包时)解决这个问题。我尝试了各种绝对导入、相对导入,通过获取当前文件的位置将其附加到sys.path。我的直觉告诉我这与程序运行时的sys.path有关
感谢您在这个问题上提供的帮助。您能在需要使用
方法之前加载它吗?谁给了您这个代码库让您使用?这听起来真的很像系统中内置的循环导入-除非B.b1
的其他定义是c2.py
试图引用的,否则实际上是文件在一个循环中相互导入,这会导致ImportError
。现在,我了解到您正在混淆名称-可能是巧合,包的名称
与应该调用的外部包的名称相同,在这种情况下,pythonpath可能是问题所在。重新组织您的包。如果b
依赖于c
和c
依赖于b
,则您的结构不好。在它们之间的关系中,一个应该扮演进口角色,另一个应该扮演进口角色。根据您重组的能力,您可以使用相对进口(例如,来自..B.b1
,而不是来自Package.B.b1
)但是,如果您坐在B
和C
模块之外,无法修改它们中的任何一个,那么它似乎只是一个构建糟糕的系统,而不是从X导入Y
导入模块导入X
或从X导入。在您的示例场景中,将c2.py中的import语句替换为Package.B.b1 import*中的,可以节省时间(因为在导入过程中,会检测到模块已经在内存中),但更好的解决方案是重新组织代码以避免这种情况。您能在需要使用方法之前加载方法\u b2
吗?谁给了您这个代码库?这听起来真的很像系统中内置的循环导入-除非B.b1
的其他定义是c2.py
试图引用的,否则实际上是文件在一个循环中相互导入,这会导致ImportError
。现在,我了解到您正在混淆名称-可能是巧合,包的名称
与应该调用的外部包的名称相同,在这种情况下,pythonpath可能是问题所在。重新组织您的包。如果b
依赖于c
和c
依赖于b
,则您的结构不好。在它们之间的关系中,一个应该扮演进口角色,另一个应该扮演进口角色。根据您重组的能力,您可以使用相对进口(例如,来自..B.b1
,而不是来自Package.B.b1
)但是,如果您坐在B
和C
模块之外,无法修改它们中的任何一个,那么它似乎只是一个构建糟糕的系统,而不是从X导入Y
导入模块导入X
或从X导入。在您的示例场景中,将c2.py中的import语句替换为Package.B.b1 import*可以节省时间(因为在导入过程中,会检测到模块已经在内存中),但更好的解决方案是重新组织代码以避免这种情况。