Python:导入具有相互依赖关系的模块

时间:2015-03-01 22:31:51

标签: python dependencies

我有两个文件rest_api.pyContact.py。联系人类似于域对象(包含Contact类),而rest_api具有设置应用程序的功能。

rest_api我有以下几行:

from Contact import Contact
...
client = MongoClient('localhost',27017)
collection = client.crypto_database.test_collection
def dbcollection(){
     return collection
}
...
api.add_resource(Contact,'/contact/<string:contact_id>')

Contact中,我尝试执行以下操作:

from rest_api import dbcollection

class Contact(Resource):
    def get(self,contact_id):
        result = {}
        result['data'] = dbcollection.find_one({'contact_id':contact_id})
        result['code'] = 200 if result['data'] else 404
        return make_response(dumps(result), result['code'],{"Content-type": "application/json"})

此操作失败,并显示以下错误: ImportError: cannot import name Contact

导入联系人的正确方法是什么,以便它还可以使用rest_api中的变量/函数?

p.s如果我将收集代码移动到另一个文件,并导入该文件而不是工作,但我认为还有其他方法..

2 个答案:

答案 0 :(得分:2)

这是循环导入依赖项,无法解决。问题是,导入python模块确实运行代码,必须遵循一些顺序,其中一个模块必须先行。

我想说将支持代码放在不同的文件中是正确的方法。

但是,在这种情况下,导入时实际上并不需要dbcollection。因此,您可以通过从模块级别导入get函数来解决此问题。例如

class Contact(Resource):
    def get(self,contact_id):
        from rest_api import dbcollection
        result = {}
        result['data'] = dbcollection.find_one({'contact_id':contact_id})
        result['code'] = 200 if result['data'] else 404
        return make_response(dumps(result), result['code'],{"Content-type": "application/json"})

类似的方法如下:

import rest_api

class Contact(Resource):
    def get(self,contact_id):
        result = {}
        result['data'] = rest_api.dbcollection.find_one({'contact_id':contact_id})
        result['code'] = 200 if result['data'] else 404
        return make_response(dumps(result), result['code'],{"Content-type": "application/json"})

这应该可行,因为python会努力解决循环导入依赖关系:当它开始导入模块时,它会为该模块创建一个空模块dict。然后,当它找到嵌套导入时,它将继续执行该导入。如果依次导入已经在导入过程中的模块,它只是跳过它。因此,在加载Contact.py时,import rest_api只接受已存在的模块字典。由于它还不包含dbcollectionfrom rest_api import dbcollection失败。然而,一个简单的import rest_api可以正常工作,因为它的成员仅在Contact.py完成导入后解决(除非您在模块级别从内部调用Contact.get)。

答案 1 :(得分:0)

假设您还没有了解哪些模块将导入哪些模块,您可以自己跟踪,而不是导入。

在__init__.py中,定义这些 -

__module_imports__ = {}

def requires_module(name):
    return name not in __module_imports__

def importing_module(name):
    __module_imports__[name] = True

然后,在每个类文件的顶部,您定义类的位置,将以下内容添加到this_module.py:

from my_modules import requires_module, importing_module

importing('ThisModule')
if requires_module('ThatModule')
    from my_modules.that_module import ThatModule

class ThisModule:
    """ Real Stuff Goes Here """
    pass

和this_module.py:

from my_modules import requires_module, importing_module

importing('ThatModule')
if requires_module('ThisModule')
    from my_modules.this_module import ThisModule

class ThatModule:
    """ Real Stuff Goes Here """
    pass

现在你可以获得你的导入,无论先导入哪些导入或其他任何导入。