我正在使用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
我不知道这应该如何解决我的导入问题。
答案 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
转换为模块,并将ActionModel
和AreaModel
代码放入其中。
℃。将ActionModel
和AreaModel
的共享代码/功能移动到他们导入的基本模块中。
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)
这称为对象组合。