深夜发贴求优雅破Python导入依赖问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
banxi1988
V2EX    Python

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

  •  
  •   banxi1988
    banxi1988 2013-06-13 02:06:20 +08:00 8259 次点击
    这是一个创建于 4562 天前的主题,其中的信息可能已经有所发展或是发生改变。
    问题详情:
    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

    怎么破这种导入问题?
    14 条回复    2015-01-15 13:57:06 +08:00
    keakon
        1
    keakon  
       2013-06-13 03:13:42 +08:00
    最省事的方法就是都写在一个文件里,我经常这么干。

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

    麻烦一点的办法就是避免 from ... import ...,只用 import ...。
    ufo22940268
        2
    ufo22940268  
       2013-06-13 04:58:30 +08:00 via iPhone
    很想知道发生这个问题的原因是什么,我就算在文件内导入也常常发生这个问题,求资料
    ruoyu0088
        3
    ruoyu0088  
       2013-06-13 06:53:48 +08:00   2
    yetone
        4
    yetone  
       2013-06-13 07:58:25 +08:00 via Android
    哈哈,我一般是这样做的。
    import models as m
    然后直接 m.A m.B m.C 就好了
    当然,前提是你要在 __init__.py 中把 A B C 都导入
    banxi1988
        5
    banxi1988  
    OP
       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
        6
    swulling  
       2013-06-13 10:46:44 +08:00
    调整import顺序可破。
    ufo22940268
        7
    ufo22940268  
       2013-06-13 11:27:36 +08:00
    @ruoyu0088 真是牛逼,我翻遍网络找不到这个,结果你找到了。这是我搜索能力不够呢,还是不重视文档里面的faq呢
    banxi1988
        8
    banxi1988  
    OP
       2013-06-13 13:33:49 +08:00
    @swulling 循环引用的话不是调整import顺序可破的。单向引用的才可以。


    像我上面的问题,我想到一个稍微好一点的解决办法是:
    因为models中的各个db.Model的子类。所在的模块只是个大概的分类。
    所以。我是先将。bm模块中引用到am模型中的类,移动到bm中。am中的类也尽量做到不引用bm模块中的类。如果实在需要引用。就在对应方法中导入。将循环变成单向。
    ianluo
        9
    ianluo  
       2013-06-13 14:11:42 +08:00
    这种问题更多应该是设计的问题我觉得
    banxi1988
        10
    banxi1988  
    OP
       2013-06-13 16:57:47 +08:00
    @ianluo 是啊,我也觉得是Python的导入机制的设计问题。因为如果你用Java的话,你永远不会遇到这种问题的。。
    binux
        11
    binux  
       2013-06-13 17:35:13 +08:00
    @banxi1988 我觉得 @ianluo 的意思是,你的设计有问题,不应该有相互引用
    yangzh
        12
    yangzh  
       2013-06-14 01:15:35 +08:00
    把各个模块再细分,耦合度再降低。
    swulling
        13
    swulling  
       2013-06-19 15:33:53 +08:00   1
    @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
        14
    chevalier  
       2015-01-15 13:57:06 +08:00
    调整import顺序 +1
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5111 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 39ms UTC 01:17 PVG 09:17 LAX 17:17 JFK 20:17
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86