pythonanywhere 中的相对导入在 Flask 项目中不起作用

Relative imports in pythonanywhere do not work in flask project

我正在尝试从一个非常有用的教程中学习

https://www.digitalocean.com/community/tutorials/how-to-add-authentication-to-your-app-with-flask-login

关于如何使用 flask_login.

我的问题:完整教程在我的本地 PC 上运行良好,但是我 运行 在尝试在 pythonanywhere[=69] 上获取此 运行ning 时遇到问题=].

该错误似乎与相关导入无关。在最好的情况下,我想提出一些代码,这些代码 运行 在我的机器和 pythonanywhere 上都是本地的。

举个最小的例子,项目结构如下:

└── flask_auth_app
    └── project
        ├── __init__.py       
        ├── auth.py           
        ├── main.py        

与文件

__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy()

def create_app():
    app = Flask(__name__)

    app.config['SECRET_KEY'] = 'secret-key-goes-here'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'

    db.init_app(app)

    # blueprint for auth routes in our app
    from .auth import auth as auth_blueprint
    app.register_blueprint(auth_blueprint)

    # blueprint for non-auth parts of app
    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)

    return app 

auth.py

from flask import Blueprint
from . import db

auth = Blueprint('auth', __name__)

@auth.route('/login')
def login():
    return 'Login'

@auth.route('/signup')
def signup():
    return 'Signup'

@auth.route('/logout')
def logout():
    return 'Logout'    

main.py

from flask import Blueprint
from . import db

main = Blueprint('main', __name__)

@main.route('/')
def index():
    return 'Index'

@main.route('/profile')
def profile():
    return 'Profile' 

为了在我的本地 PC 上执行此操作,我创建了一个环境变量

set FLASK_APP=project
来自 flask_auth_app 目录的

和 运行 烧瓶

flask run

一切都运行很好。

我现在已经将文件传输到 pythonanywhere 并在那里使用以下配置:

source code: /home/grammaster/flask_auth_app
working directory: /home/grammaster/flask_auth_app

WSGI配置文件

# This file contains the WSGI configuration required to serve up your
# web application at http://<your-username>.pythonanywhere.com/
# It works by setting the variable 'application' to a WSGI handler of some
# description.
#
# The below has been auto-generated for your Flask project

import sys

# add your project directory to the sys.path
project_home = '/home/grammaster/flask_auth_app/project'
if project_home not in sys.path:
    sys.path = [project_home] + sys.path

# import flask app but need to call it "application" for WSGI to work
from project import app as application  # noqa

产生的错误信息是

2021-08-13 05:58:26,704: Error running WSGI application
2021-08-13 05:58:26,706: ImportError: cannot import name 'app' from 'project' (/home/grammaster/flask_auth_app/./project/__init__.py)
2021-08-13 05:58:26,706:   File "/var/www/grammaster_pythonanywhere_com_wsgi.py", line 16, in <module>
2021-08-13 05:58:26,707:     from project import app as application  # noqa

如果我将设置更改为

source code: /home/grammaster/flask_auth_app/project
working directory: /home/grammaster/flask_auth_app/project

并使用

from main import app as application  # noqa

结果错误是

2021-08-13 06:10:53,086: Error running WSGI application
2021-08-13 06:10:53,089: ImportError: attempted relative import with no known parent package
2021-08-13 06:10:53,089:   File "/var/www/grammaster_pythonanywhere_com_wsgi.py", line 16, in <module>
2021-08-13 06:10:53,089:     from main import app as application  # noqa
2021-08-13 06:10:53,089: 
2021-08-13 06:10:53,089:   File "/home/grammaster/flask_auth_app/project/main.py", line 2, in <module>
2021-08-13 06:10:53,089:     from . import db

我确信这个问题相当微不足道,但我似乎对 pythonanywhere 和一般的 Flask 服务器上的相关导入缺乏一些基本的了解。

我终于找到了使上述示例在 pythonanywhere 上使用相对导入的解决方案。问题源于 WSGI 配置文件中的错误路径。

对于上面的示例和路径,正确的 WSGI 配置文件

# This file contains the WSGI configuration required to serve up your
# web application at http://<your-username>.pythonanywhere.com/
# It works by setting the variable 'application' to a WSGI handler of some
# description.
#
# The below has been auto-generated for your Flask project

import sys

# add your project directory to the sys.path
project_home = '/home/grammaster/flask_auth_app'
if project_home not in sys.path:
    sys.path = [project_home] + sys.path

# import flask app but need to call it "application" for WSGI to work
from project import create_app
application = create_app()