从同一目录导入模块时,模块“ a”没有属性“ b”

时间:2018-06-28 08:43:48

标签: python python-3.x python-import attributeerror

我的Python项目中具有以下目录结构:

    - dump_specs.py
    /impa
        - __init__.py
        - server.py
        - tasks.py

我对循环引用有疑问。 dump_specs.py需要引用app中的server.pyserver.py是一款Flask应用,需要引用tasks.py中的芹菜任务。因此dump_specs.py看起来像:

#!/usr/bin/env python3

import impa.server

def dump_to_dir(dir_path):
    # Do something
    client = impa.server.app.test_client()
    # Do the rest of things

impa/server.py如下:

#!/usr/bin/env python3

import impa.tasks

app = Flask(__name__)

# Definitions of endpoints, some of them use celery tasks -
# that's why I need impa.tasks reference

还有impa/tasks.py

#!/usr/bin/env python3

from celery import Celery

import impa.server

def make_celery(app):
    celery = Celery(app.import_name,
                broker=app.config['CELERY_BROKER_URL'],
                backend=app.config['CELERY_RESULT_BACKEND'])
    TaskBase = celery.Task

    class ContextTask(TaskBase):
        abstract = True

        def __call__(self, *args, **kwargs):
            with app.app_context():
                return TaskBase.__call__(self, *args, **kwargs)

    celery.Task = ContextTask
    return celery

celery = make_celery(impa.server.app)

当我尝试使用./dump_specs.py转储规范时,出现错误:

./dump_specs.py specs
Traceback (most recent call last):
  File "./dump_specs.py", line 9, in <module>
    import impa.server
  File "/build/impa/server.py", line 23, in <module>
    import impa.tasks
  File "/build/impa/tasks.py", line 81, in <module>
    celery = make_celery(impa.server.app)
    AttributeError: module 'impa' has no attribute 'server'

我不明白怎么了。有人可以解释发生了什么以及如何消除此错误吗?

1 个答案:

答案 0 :(得分:0)

如果我设法在主机上正确再现了您的问题,它应该可以帮助您将import impa.tasks插入dump_specs.py上方 import impa.server

模块之间相互依赖的方式,加载顺序很重要。 IIRC(文档中更详细地介绍了加载机制),当您首次尝试导入impa.server时,它将在第23行尝试导入impa.tasks,但是导入impa.server是在这一点上还不完整。 import impa.server中有impa.tasks,但是我们现在没有回来导入它(否则我们将以一个完整的圈结束)并继续导入impa.tasts,直到我们想要访问impa.server.app,但我们还没有做到这一点,impa.server尚未导入。

在可能的情况下,如果未在导入时执行访问包中另一个模块的代码(直接作为模块的一部分而不是位于函数或类中,而该函数或类将在调用之后使用)也将有所帮助。导入已完成)。