简体   繁体   English

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

[英]Unable to import method from another python file

I am currently working on a backend api based off of this example: https://github.com/gothinkster/flask-realworld-example-app我目前正在基于以下示例开发后端 api: https://github.com/gothinkster/flask-realworld-example-app

I am new to python and I am having an issue with getting imports to work.我是 python 的新手,我遇到了让导入工作的问题。 I am simply not understanding the import rules that python follows based on the inconsistencies that I am noticing in the ability to import the necessary functions.我根本不理解 python 遵循的导入规则,因为我注意到导入必要功能的能力存在不一致。 In certain cases the imports word fine, but then in others it does not.在某些情况下,导入词很好,但在其他情况下则不然。

api/user/serializers.py: api/用户/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: 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')

The issue I am having is occuring inside of the "serializers" file.我遇到的问题发生在“序列化程序”文件中。 Once I run the api and try to to call the /login/ path of my API, it tries to call the serializer and then I get the following error:一旦我运行 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'

This import works in other places though.但是,此导入在其他地方也有效。 For example in the app/extensions.py the import works but only if I put it right in front of the jwt variable.例如,在 app/extensions.py 中,导入有效,但前提是我将它放在 jwt 变量的前面。 If I put the import at the top, then I got an error that "db" could not be imported in other places:如果我将导入放在顶部,那么我会得到一个错误,“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

Complete Trace:完整的跟踪:

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'

This traceback shows clearly what happened:这个回溯清楚地显示了发生了什么:

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'

There is this:有这个:

  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

and doing that ends up doing this:这样做最终会这样做:

  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

In other words, from api.utils import must_not_be_blank is executed while api.utils is already being imported.换句话说, from api.utils import must_not_be_blankapi.utils已经被导入时执行。 At that point, api.utils is half-done and importing something from it may fail.此时, api.utils已完成一半,从中导入某些内容可能会失败。 And it does fail.它确实失败了。

That is called a circular import.这称为循环导入。 You should reorganize the code so that you don't have circular imports, ie if A imports B and B imports C , then C should not import A or B .您应该重新组织代码,以便您没有循环导入,即如果A导入BB导入C ,那么C不应导入AB

It happens very likely due to circular dependency between some modules.这很可能是由于某些模块之间的循环依赖而发生的。 The easiest way to check would be taking look at the dependency graph of the whole project.最简单的检查方法是查看整个项目的依赖关系图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM