【问题标题】:Web.py NameError When Importing Module in Module在模块中导入模块时的Web.py NameError
【发布时间】:2014-02-20 13:42:36
【问题描述】:

我正在 python 2.7.3 上使用 web.py 创建一个 Web 应用程序。 我有以下文件夹结构:

start_app.py
/app
   __init__.py
   /models
      __init__.py
      ActionModel.py
      AreaModel.py
   /controllers
      __init__.py
      world.py
   /views

每当我使用python start_app.py 重新启动应用程序并访问world/surrounding 时,我都会收到以下错误

<type 'exceptions.ImportError'> at /world/surrounding
cannot import name AreaModel
Python  /home/dev/app/models/ActionModel.py in <module>, line 13
Web     GET http://localhost:5000/world/surrounding

第 13 行很简单:from app.models import AreaModel,但我不明白为什么 python 在这里抱怨。

如果我评论这个导入行,它运行良好。但是,如果我调用不同的 URL,例如world/view,我收到未定义 AreaModel 的错误。一旦我取消注释该行,它就会再次适用于所有情况(即 /surrounding 和 /view)。

我怀疑这与我“循环导入”这一事实有关,即 world.py 导入 AreaModel,AreaModel 导入 ActionModel,ActionModel 导入 AreaModel。 我怀疑这是做事情的“pythonic 方式”,甚至是“MVC 方式”,所以我非常感谢你能启发我如何正确地做到这一点。

注意:app 不在我的 PYTHONPATH 中,但我认为这里不需要它,因为 start_app.py 位于顶级目录中,根据this,所有模块都应该可用。

基本上,归结为: 我需要控制器和模型中的模型功能。 “循环导入”是一种好习惯吗?还是有更好的方法来做到这一点? 另外,这个问题是一般的python还是web.py?

更新: 添加了 init.py 文件,我有它们,但未包含在原始问题中。很抱歉。

更新: ActionModel.py 包括(除其他外)一个名为 BaseAction 的类和一些函数,它们根据我们正在处理的 Action 类型返回 BaseAction 的实例或子类。它们被称为使用例如ActionModel.get_by_id()

@matthew-trevor :您是否在 a) 中建议我应该将这些函数 get_by_id() 移动到类 ActionModel 中?

#actionmodel.py
class ActionModel(object):
    def __init__(arg1, arg2, area_class):
        self.area = area_class()

    def get_by_id(self, id):
        return BaseAction(id)

class BaseAction(object):
    def __init__(id):
        pass

我不明白这应该如何解决我的导入问题。

【问题讨论】:

    标签: python python-2.7 import module web.py


    【解决方案1】:

    迫在眉睫的问题

    您不能从文件夹中导入,但您可以从包中导入。您可以通过添加__init__.py 文件将任何文件夹变成一个包:

    start_app.py
    /app
       __init__.py
       /models
          __init__.py
          ActionModel.py
          AreaModel.py
       /controllers
          __init__.py
          world.py
       /views
          __init__.py
    

    我猜ActionModel.py 包含一个同名的类。如果是这样,我建议将文件重命名为 actionmodel.py 以将其与类区分开来。

    循环导入

    “循环导入”是一种好习惯吗?或者有没有更好的 这样做的方法?

    这不仅是不好的做法,而且是行不通的。有几种方法可以解决这个问题,这主要取决于您要做什么:

    一个。在AreaModel 中,导入ActionModel 模块,然后通过属性查找引用您想在其中使用的任何内容,反之亦然:

    # areamodel.py
    import actionmodel
    
    def foo():
        action = actionmodel.ActionModel(...)
    

    只要引用在类或函数定义中,它只会在运行时发生,而不是在导入期间发生,因此避免了循环引用。

    b.把models变成一个模块,把ActionModelAreaModel代码都放进去。

    c。将 ActionModelAreaModel 的共享代码/功能移动到它们都从中导入的基本模块中。

    d。让你的ActionModel 类(或其他)接受一个类作为输入,然后将AreaModel 传递给world.pyAreaModel 同上)。这样,ActionModel 不需要包含对 AreaModel 的引用,它只需要知道如何处理它:

    # actionmodel.py
    class ActionModel(object):
        def __init__(arg1, arg2, area_class):
            self.area = area_class()
    
    # areamodel.py
    class AreaModel(object):
        def __init__(action_class):
            self.action = action_class()
    
    # world.py
    from actionmodel import ActionModel
    from areamodel import AreaModel
    
    action = ActionModel('foo', 'bar', AreaModel)
    area = AreaModel(ActionModel)
    

    这称为对象组合。

    【讨论】:

    • 我有 init.py 文件,所以这不是问题。无论如何,谢谢你指出这一点。我添加了它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多