- 背景故事
最近在做一个自动化运维的小项目,后台用的python(ansible, flask 等等..) , 然后习惯性的搞了一些package像平时写java项目一样,比如
com.don2ccc.xxx
这样。。然后在某个类里面去引用其他的,比如:
com.don2ccc.engines
-> alertengine.py
com.don2ccc.managers
-> servermanager.py
然后比如我在alertengine.py里面想去用下servermanager.py里面的getUATServerLists()这个方法,
我会先alertengine.py的最上面,
import com.don2ccc.managers.servermanager as smgr
然后写个啥方法:
def willDoSomething():
uatservers = smgr.getUATServerLists()
# other logic with uatservers obj....
对吧,这样很正常嘛自己想来,eclipse 里面也完全没问题...
but...but...but
当搞到服务器上面了,事情就不一样了...
嗯。本地eclipse里面跑着是没有任何问题的,但是把这包东西搞到服务器后,一跑,就出现了各种地方都在报
AttributeError: 'module' object has no attribute
- 这是肿么了
下面这个帖子很有用哦,本人python也属于自学,还没成才的那种类型,就不装神弄鬼了,直接上链接:
https://stackoverflow.com/questions/1250103/attributeerror-module-object-has-no-attribute
说白了,大意就是,
You have mutual top-level imports, which is almost always a bad idea.
If you really must have mutual imports in Python, the way to do it is to import them within a function:
# In b.py:
def cause_a_to_do_something():
import a
a.do_something()
Now a.py can safely do import b without causing problems.
(At first glance it might appear that cause_a_to_do_something() would be hugely inefficient because it does an import every time you call it, but in fact the import work only gets done the first time. The second and subsequent times you import a module, it's a quick operation.)
所以这里接上一段,我这边怎么解决呢?
直接在方法体里面去引用,就绝对没问题了。
def willDoSomething():
import com.don2ccc.managers.servermanager as smgr
uatservers = smgr.getUATServerLists()
# other logic with uatservers obj....
- 最后,如果你碰巧读到我这个文章,那么说明你和我一样,需要好好学习下面这段话:
- https://stackoverflow.com/questions/744373/circular-or-cyclic-imports-in-python
There was a really good discussion on this over at comp.lang.python last year. It answers your question pretty thoroughly.
Imports are pretty straightforward really. Just remember the following:
'import' and 'from xxx import yyy' are executable statements. They execute when the running program reaches that line.
If a module is not in sys.modules, then an import creates the new module entry in sys.modules and then executes the code in the module. It does not return control to the calling module until the execution has completed.
If a module does exist in sys.modules then an import simply returns that module whether or not it has completed executing. That is the reason why cyclic imports may return modules which appear to be partly empty.
Finally, the executing script runs in a module named __main__, importing the script under its own name will create a new module unrelated to __main__.
Take that lot together and you shouldn't get any surprises when importing modules.