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 · 7910 次点击
    这是一个创建于 4164 天前的主题,其中的信息可能已经有所发展或是发生改变。
    问题详情:
    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   ·   实用小工具   ·   3150 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 13:35 · PVG 21:35 · LAX 05:35 · JFK 08:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.