2017-09-14 70 views
1

我有这样的代码导入错误:不能两个文件之间导入名导入相同

mainModule

from src.comp.mypackage.wait import Wait 
from src.comp.mypackage.men import Men, MenItem 

""" Code and stuff using Men and MenItem """ 

if __name__ == '__main__': 
    MenuTestDrive.main() 

男人

from abc import ABCMeta, abstractmethod 
from src.comp.mypackage.util import NullUtil, CompUtil 

UTIL

from src.comp.mypackage.stack import Stack 
from src.comp.mypackage.men import Men 

""" Code and stuff using Men and MenItem """ 

和运行mainModule时,我正在给这个错误:

Traceback (most recent call last): 
    File "/home/user/PycharmProjects/pythonProj/pythonDesignPatterns/src/comp/mypackage/mainModule.py", line 2, in <module> 
    from pythonDesignPatterns.src.comp.mypackage.men import Men, MenItem 
    File "/home/user/PycharmProjects/pythonProj/pythonDesignPatterns/src/comp/mypackage/men.py", line 2, in <module> 
    from pythonDesignPatterns.src.comp.mypackage.iterator import NullUtil, CompUtil 
    File "/home/user/PycharmProjects/pythonProj/pythonDesignPatterns/src/comp/mypackage/util.py", line 2, in <module> 
    from pythonDesignPatterns.src.comp.mypackage.men import Men 

ImportError: cannot import name 'Men' 

我使用pyCharm,但错误在命令行是一样的。

我可以提供更多的代码,但我不认为有任何使用类的幻想,只会分散注意力。

我应该在哪里寻找失败?

+0

名字'男人'真的存在'男人'包?你能否在你的问题中提供它的定义? – Grigoriy

回答

2

TL; DR:蟒蛇不允许圆形进口,所以你不能有模块men从模块util进口,如果模块util进口模块men

较长的答案:

你要明白,在Python importclassdef等其实都是可执行语句和一切(或几乎)发生在运行时。在给定进程中首次导入模块时,所有顶级语句都将按顺序执行,将创建一个module实例对象,并将所有顶级名称作为属性(请注意,classdefimport都绑定了名称)并插入到sys.modules缓存字典中,以便相同模块的下一个导入将直接从缓存中检索。

在你的情况下,首先导入时,该men模块试图导入util模块,这是不是在sys.modules却又如此Python运行时所处的util.py(或.pyc文件)文件并执行它。然后它到达from src.comp.mypackage.men import Men。此时,men.py尚未完全执行,因此没有Men属性。

规范的解决方案是将循环依赖提取到第三个模块中,或者将两个模块合并为一个模块,具体取决于一个对您的具体情况有意义的事情(目标是一如既往地让模块具有低耦合和高凝聚力)。 FWIW,即使语言支持它们,循环依赖也被认为是不好的设计。

有时(大多数情况下,在复杂的框架中,将某些特定结构强加给您的代码和特定的导入顺序),最终可能会出现循环依赖链或者更复杂(如A.funcX依赖于By,B取决于依赖于D的C,它依赖于最终依赖于A.funcZ的E)和/或非常难以以有意义的方式干净地重构。作为最后的手段,您仍然可以在函数中推迟一些导入语句(在上面它将在A.funcX之内)。这是仍然认为是一种不好的做法,应该只能作为最后的手段使用。

作为便笺:从您的软件包命名方案我可以闻到强大的Java影响力。 Python不是Java!不是说Java有什么问题,它只是these are two wildly different languageswildly different designs, idioms and philosopies

试图在Python中强制使用Java习语和习惯最好是在痛苦和沮丧的经历(这里已经完成了......),所以我的建议是:忘记你学习Java的大部分内容,开始学习Python(而不仅仅是语法 - 语法实际上只是语言的一部分,不一定是最重要的语法)。在Python中,我们倾向于平面嵌套,并且不要尝试为每个类使用一个模块,您可以在一个模块中包含整个(微)框架,如果没有实际的理由将其分解为子模块,那也没关系。

+0

这是一个从Java翻译而来的设计模式源代码,但总的来说,我将模型类似的对象分组,并且在它们不配合任何对象(如Java接口)等时合并对象。但是对于这些模式,一些Java设计依赖于。无论如何感谢您的建议,这是一个很好的建议 – madtyn