无法从另一个python文件导入方法

时间:2019-10-21 16:00:33

标签: python flask

根据以下示例,我目前正在使用后端api:https://github.com/gothinkster/flask-realworld-example-app

我是python的新手,在导入工作方面遇到了问题。我根本不理解python基于导入功能的不一致性而遵循的导入规则。在某些情况下,导入词可以罚款,但在其他情况下则不能。

api / user / serializers.py:

# coding: utf-8
from marshmallow import Schema, fields, pre_load, post_dump
from api.utils import must_not_be_blank


class UserSchema(Schema):
    username = fields.Str(validate=[must_not_be_blank])
    email = fields.Email(validate=[must_not_be_blank])
    password = fields.Str(validate=[must_not_be_blank], load_only=True)
...

api / utils.py:

# -*- coding: utf-8 -*-
"""Helper utilities and decorators."""
from api.user.models import User  # noqa
from marshmallow import ValidationError
import re


def jwt_identity(payload):
    return User.get_by_id(payload)


def identity_loader(user):
    return user.id


def must_not_be_blank(data):
    if not data:
        raise ValidationError('Data not provided.')


def contains_only_letters(data):
    if not re.match("^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$", str(data)):
        raise ValidationError('Invalid String')


def validate_uga_id(uga_id):
    if uga_id.isdigit() is False:
        raise ValidationError('Not a valid UGA ID')


def validate_phone_number(phone_number):
    if not re.match(r"^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$", phone_number):
        raise ValidationError('Invalid phone number')

我遇到的问题出现在“ serializers”文件中。一旦我运行api并尝试调用API的/ login /路径,它就会尝试调用序列化程序,然后出现以下错误:

File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/serializers.py", line 3, in <module> from api.utils import must_not_be_blank ImportError: cannot import name 'must_not_be_blank'

此导入可在其他地方使用。例如,在app / extensions.py中,导入有效,但前提是我将其放在jwt变量前面。如果我将导入放在顶部,那么我将收到一个错误消息,即“ db”无法在其他地方导入:

# -*- coding: utf-8 -*-
"""Extensions module. Each extension is initialized in the app factory located in app.py."""

from flask_bcrypt import Bcrypt
from flask_caching import Cache
from flask_cors import CORS
from flask_jwt_extended import JWTManager
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy, Model


class CRUDMixin(Model):
    """Mixin that adds convenience methods for CRUD (create, read, update, delete) operations."""

    @classmethod
    def create(cls, **kwargs):
        """Create a new record and save it the database."""
        instance = cls(**kwargs)
        return instance.save()

    def update(self, commit=True, **kwargs):
        """Update specific fields of a record."""
        for attr, value in kwargs.items():
            setattr(self, attr, value)
        return commit and self.save() or self

    def save(self, commit=True):
        """Save the record."""
        db.session.add(self)
        if commit:
            db.session.commit()
        return self

    def delete(self, commit=True):
        """Remove the record from the database."""
        db.session.delete(self)
        return commit and db.session.commit()


# A storage engine to save revoked tokens. In production if
# speed is the primary concern, redis is a good bet. If data
# persistence is more important for you, postgres is another
# great option. In this example, we will be using an in memory
# store, just to show you how this might work. For more
# complete examples, check out these:
# https://github.com/vimalloc/flask-jwt-extended/blob/master/examples/redis_blacklist.py
# https://github.com/vimalloc/flask-jwt-extended/tree/master/examples/database_blacklist
blacklist = set()
bcrypt = Bcrypt()
db = SQLAlchemy(model_class=CRUDMixin)
migrate = Migrate()
cache = Cache()
cors = CORS()

from api.utils import jwt_identity, identity_loader  # noqa

jwt = JWTManager()
jwt.user_loader_callback_loader(jwt_identity)
jwt.user_identity_loader(identity_loader)

# For this example, we are just checking if the tokens jti
# (unique identifier) is in the blacklist set. This could
# be made more complex, for example storing all tokens
# into the blacklist with a revoked status when created,
# and returning the revoked status in this call. This
# would allow you to have a list of all created tokens,
# and to consider tokens that aren't in the blacklist
# (aka tokens you didn't create) as revoked. These are
# just two options, and this can be tailored to whatever
# your application needs.
@jwt.token_in_blacklist_loader
def check_if_token_in_blacklist(decrypted_token):
    jti = decrypted_token['jti']
    return jti in blacklist

完整跟踪:

Traceback (most recent call last):
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/autoapp.py", line 5, in <module>
    from api.app import create_app
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/app.py", line 4, in <module>
    from api.extensions import bcrypt, cache, db, migrate, jwt, cors
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/extensions.py", line 55, in <module>
    from api.utils import jwt_identity, identity_loader  # noqa
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/utils.py", line 3, in <module>
    from api.user.models import User  # noqa
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/__init__.py", line 3, in <module>
    from . import views  # noqa
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/views.py", line 14, in <module>
    from .serializers import user_schema
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/serializers.py", line 3, in <module>
    from api.utils import must_not_be_blank
ImportError: cannot import name 'must_not_be_blank'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/venv/lib/python3.6/site-packages/flask/cli.py", line 338, in __call__
    self._flush_bg_loading_exception()
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/venv/lib/python3.6/site-packages/flask/cli.py", line 326, in _flush_bg_loading_exception
    reraise(*exc_info)
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/venv/lib/python3.6/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/venv/lib/python3.6/site-packages/flask/cli.py", line 314, in _load_app
    self._load_unlocked()
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/venv/lib/python3.6/site-packages/flask/cli.py", line 330, in _load_unlocked
    self._app = rv = self.loader()
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/venv/lib/python3.6/site-packages/flask/cli.py", line 388, in load_app
    app = locate_app(self, import_name, name)
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/venv/lib/python3.6/site-packages/flask/cli.py", line 247, in locate_app
    "\n\n{tb}".format(name=module_name, tb=traceback.format_exc())
flask.cli.NoAppException: While importing "autoapp", an ImportError was raised:

Traceback (most recent call last):
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/venv/lib/python3.6/site-packages/flask/cli.py", line 240, in locate_app
    __import__(module_name)
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/autoapp.py", line 5, in <module>
    from api.app import create_app
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/app.py", line 4, in <module>
    from api.extensions import bcrypt, cache, db, migrate, jwt, cors
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/extensions.py", line 55, in <module>
    from api.utils import jwt_identity, identity_loader  # noqa
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/utils.py", line 3, in <module>
    from api.user.models import User  # noqa
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/__init__.py", line 3, in <module>
    from . import views  # noqa
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/views.py", line 14, in <module>
    from .serializers import user_schema
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/serializers.py", line 3, in <module>
    from api.utils import must_not_be_blank
ImportError: cannot import name 'must_not_be_blank'

2 个答案:

答案 0 :(得分:1)

此回溯清楚地表明发生了什么:

Traceback (most recent call last):
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/autoapp.py", line 5, in <module>
    from api.app import create_app
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/app.py", line 4, in <module>
    from api.extensions import bcrypt, cache, db, migrate, jwt, cors
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/extensions.py", line 55, in <module>
    from api.utils import jwt_identity, identity_loader  # noqa
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/utils.py", line 3, in <module>
    from api.user.models import User  # noqa
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/__init__.py", line 3, in <module>
    from . import views  # noqa
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/views.py", line 14, in <module>
    from .serializers import user_schema
  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/serializers.py", line 3, in <module>
    from api.utils import must_not_be_blank
ImportError: cannot import name 'must_not_be_blank'

有这个:

  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/extensions.py", line 55, in <module>
    from api.utils import jwt_identity, identity_loader  # noqa

并最终执行以下操作:

  File "/Users/Shawn/Desktop/Computer Science/CSCI4050 Software Engineering/flask-realworld-example-app/api/user/serializers.py", line 3, in <module>
    from api.utils import must_not_be_blank

换句话说,from api.utils import must_not_be_blank是在已经导入api.utils的情况下执行的。此时,api.utils已完成一半,从中导入内容可能会失败。而且确实失败了。

这称为循环导入。您应该重新组织代码,以便没有循环导入,即,如果A导入BB导入C,则C不应导入AB

答案 1 :(得分:0)

很可能由于某些模块之间的circular dependency而发生。最简单的检查方法是查看整个项目的依赖关系图。