在模块中导入模块时出现Web.py NameError

时间:2014-01-29 00:00:34

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

我正在使用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会在这里抱怨。

如果我评论此导入行,它运行正常。但是,如果我拨打其他网址,例如world/view,我收到一条未定义AreaModel的错误。一旦我取消注释该行,它对所有情况(即/ around和/ view)再次正常工作。

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

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

基本上,它归结为: 我需要控制器和模型中的模型功能。 “圈内进口”是一种好习惯吗?或者有更好的方法来做到这一点? 此外,这个问题一般与python有关还是只与web.py相关?

更新 添加了 init .py文件,我有了它们,但没有包含在原始问题中。对不起。

更新 ActionModel.py包括(以及其他)名为BaseAction的类和一些函数,它们返回BaseAction的实例或子类,具体取决于我们正在处理的Action类型。它们被称为使用例如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

我不知道这应该如何解决我的导入问题。

1 个答案:

答案 0 :(得分:0)

即时问题

您无法从文件夹导入,但可以从包中导入。您可以通过向其添加__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(...)

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

湾将models转换为模块,并将ActionModelAreaModel代码放入其中。

℃。将ActionModelAreaModel的共享代码/功能移动到他们导入的基本模块中。

d。让您的ActionModel类(或其他)接受一个类作为输入,然后在AreaModel中将world.py传递给它(同上AreaModel)。这样,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)

这称为对象组合。