【问题标题】:circular import landmines with Lettuce生菜循环进口地雷
【发布时间】:2012-04-30 20:00:35
【问题描述】:

我在 PyDev 中设置了 3 个项目,它们的项目引用列表中都有彼此。用于说明目的:

proj_f
    pack_foo
        mod_fooa (contains class Fooa)
        mod_foob (contains class Foob)
    mod_faa (contains class Faa)
    pack_fii
        mod_fiia (contains class Fiia)
        mod_fiib (contains class Fiib)
proj_b
    mod_bar (contains function func_bar)
    pack_baz
        mod_baza (contains class Baza)
        mod_bazb (contains class Bazb)
proj_t
    tester (what I'm running from)

再举个例子,测试人员:

from pack_foo.mod_fooa import Fooa
from pack_fii.mod_fiia import Fiia
from mod_bar import func_bar
func_bar(Fooa(), Fiia())

和 mod_bar:

from pack_foo.mod_fooa import Fooa
from pack_fii.mod_fiia import Fiia
def func_bar(fooa, fiia):
    if not fooa:
        fooa = Fooa()
    if not fiia:
        fiia = Fiia()
    fooa.do_magic()
    fiia.do_magic()

我看到的是,当我从 tester 调用它们时,一些来自 foo 的导入将在 mod_bar 中得到 ImportError: cannot import name(至关重要的是,一些但不是全部)。如果我只运行 mod_bar,导入工作正常,如果我从 mod_bar 删除依赖项和导入并从测试器运行它,它工作正常;只有当一个类的子集从 f 导入到 b 和 t 并且我从 t 运行时,它才会中断。我已经尝试阅读有关导入如何工作的文档并在谷歌上搜索解决方案,但我还没有找到任何指向正确方向的东西。我感觉这与 Python 内部的一些晦涩部分有关,但我不知道那是什么。

我认为这准确地代表了正在发生的事情,尽管从testermod_bar 的引用是间接的(tester 是我用来与我的代码,而mod_bar 实际上是生菜地形文件,生菜正在被tester 调用的其他一些模块加载。)任何人都可以为我提供至少一个开始寻找信息的地方如何解决这个问题?

编辑:

我在看这个,特别是堆栈跟踪:

Traceback (most recent call last):
  File "C:\Python27\Lib\site-packages\lettuce\__init__.py", line 53, in <module>
    terrain = fs.FileSystem._import("terrain")
  File "C:\Python27\Lib\site-packages\lettuce\fs.py", line 74, in _import
    module = imp.load_module(name, fp, pathname, description)
  File "C:\Users\adminsetup\workspace\nytd_lettuce_lib\terrain.py", line 6, in <module>
    from session.session import Session
  ImportError: cannot import name Session

terrain = fs.FileSystem._import("terrain") 中的 lettuce.__init__() 是否会导致循环导入让我感到头疼?

【问题讨论】:

    标签: python import project pydev lettuce


    【解决方案1】:

    所以是的,我得到了一个循环导入。问题是当你import lettuce 时,lettuce.py 会执行,然后它会动态导入terrain

    发生在我身上的是我有一个 Session 类,它导入 AbstractSession 反过来导入 LoggerManager,它包含一个 logging.Handler 子类,它将日志消息推送到 world 中的队列,因此 logger_manager 执行 import lettuce 到访问world。我还希望我的所有测试都从启动一个 Session 对象开始,所以我在地形中有一个 @beforeeach 方法来在每次测试之前启动一个 Session,这意味着在地形中导入 Session。

    当然,这意味着每次我在任何地方的任何文件中导入 Session 时,都会触发整个事件链(Session>AbstractSession>lettuce>terrain>Session),从而使 session.session.Session 在时间地形上未初始化尝试加载它。

    我认为我最好的解决方法是在地形中粘贴与世界相关联的日志处理程序和日志缓存,然后让地形附加处理程序本身。幸运的是,这对我来说是一个选项,因为日志记录是全局访问。这实际上在一定程度上改善了我的框架的划分,因为核心库中不会有任何关于生菜的代码,这些都将在生菜库中关闭。不过,最好的生菜没有内置这些​​地雷......

    tl;dr,如果您想尝试做的不仅仅是真正的基本测试套件,请避免使用生菜。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-06
      • 2011-01-25
      • 1970-01-01
      • 2021-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多