深夜发贴求优雅破Python导入依赖问题

2013-06-13 02:06:20 +08:00
 banxi1988
问题详情:
models/
├── __init__.py

├── mixins.py

├── am.py (有类 A,AE)

├── bm.py (有类 B,BQ)

├── cm.py (有类 C,CD)



问题在于。我想方便统一人models中导入。所以在
_init__.py上写了类似下面的代码:
from .am import A,AE
from .bm import B,BQ
from .cm import C,CD

这个时候问题出现了。
因为我的am模型里依赖B,BQ类。于是,
在am模块有 from .bm import B,BQ
而bm也模块也依赖A,AE类,于是
在bm模块有。from .am import A,AE
在这种情况下。
会报这样的错误:
ImportError: cannot import name XXX

怎么破这种导入问题?
7824 次点击
所在节点    Python
14 条回复
keakon
2013-06-13 03:13:42 +08:00
最省事的方法就是都写在一个文件里,我经常这么干。

如果你只有很少的几个地方需要用到,那就在它们内部 import。这是最简单的。

麻烦一点的办法就是避免 from ... import ...,只用 import ...。
ufo22940268
2013-06-13 04:58:30 +08:00
很想知道发生这个问题的原因是什么,我就算在文件内导入也常常发生这个问题,求资料
ruoyu0088
2013-06-13 06:53:48 +08:00
yetone
2013-06-13 07:58:25 +08:00
哈哈,我一般是这样做的。
import models as m
然后直接 m.A m.B m.C 就好了
当然,前提是你要在 __init__.py 中把 A B C 都导入
banxi1988
2013-06-13 10:23:17 +08:00
@ruoyu0088 谢谢。在上面看到了Python大神们的解法。
可是我觉得很不优雅啊。。但是也只能按照上面说的几种方法来做了。
1.重新组织代码结构,我把所有的代码放同一个文件,就不会有这样的问题了。这个时间models包也不需要了,直接变成models类了。so big a file。
2.需要时导入,如在方法(函数中导入)。尽量使用import m,而不是from <m> import <some>的方式。

@keakon 这样的话,这个文件太大了,我应该无法接受的。。。再加上把docstring算上的话,那就更大了。。天啦。简直不可想像。


@ufo22940268 ruoyu0088提供的链接也说明了这个问题。
主要是循环依赖的问题。就好比春晚的一个小品中那样:
A说:你要是有身份证我就给你开锁。B说:你给我开锁了我就能进去把身份证把锁拿给你看。
结果。就出现导入失败了。


@yetone 嗯,问题在于A,B,C互相依赖了。。所以这几个模型或者类都无法加载。。。
swulling
2013-06-13 10:46:44 +08:00
调整import顺序可破。
ufo22940268
2013-06-13 11:27:36 +08:00
@ruoyu0088 真是牛逼,我翻遍网络找不到这个,结果你找到了。这是我搜索能力不够呢,还是不重视文档里面的faq呢
banxi1988
2013-06-13 13:33:49 +08:00
@swulling 循环引用的话不是调整import顺序可破的。单向引用的才可以。


像我上面的问题,我想到一个稍微好一点的解决办法是:
因为models中的各个db.Model的子类。所在的模块只是个大概的分类。
所以。我是先将。bm模块中引用到am模型中的类,移动到bm中。am中的类也尽量做到不引用bm模块中的类。如果实在需要引用。就在对应方法中导入。将循环变成单向。
ianluo
2013-06-13 14:11:42 +08:00
这种问题更多应该是设计的问题我觉得
banxi1988
2013-06-13 16:57:47 +08:00
@ianluo 是啊,我也觉得是Python的导入机制的设计问题。因为如果你用Java的话,你永远不会遇到这种问题的。。
binux
2013-06-13 17:35:13 +08:00
@banxi1988 我觉得 @ianluo 的意思是,你的设计有问题,不应该有相互引用
yangzh
2013-06-14 01:15:35 +08:00
把各个模块再细分,耦合度再降低。
swulling
2013-06-19 15:33:53 +08:00
@banxi1988 给你举个例子吧:

http://docs.python.org/2/faq/programming.html#how-can-i-have-modules-that-mutually-import-each-other 中的foo.py bar.py为例

我们把foo.py和bar.py中的import调整下顺序

└─[$] <> cat foo.py
foo_var = 1
from bar import bar_var

─[$] <> cat bar.py
bar_var = 2
from foo import foo_var


然后我们import foo

In [1]: import foo

In [2]: foo.foo_var
Out[2]: 1

In [3]: foo.bar_var
Out[3]: 2

看,一切正常
chevalier
2015-01-15 13:57:06 +08:00
调整import顺序 +1

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/72187

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX