Flask应用程序与WSGI和Apache一起提供错误500

时间:2018-01-31 18:27:33

标签: python apache flask wsgi

我只有一个大文件服务于我的应用程序app.py,但现在,我决定拆分成几个文件来分隔代码。在此分离之后,WSGI不再启动与导入函数相关的错误。

ImportError: cannot import name month_string_to_number

现在代码分为3个主要文件: app.py,views.py models.py 。这里有一些代码,以及Apache和WSGI配置。

app.py

import sqlite3
import json
import os
import csv
import codecs
from flask import Flask, jsonify, g, request, abort, render_template, redirect, url_for, flash
from flask_sqlalchemy import Model, SQLAlchemy
from sqlalchemy import text, and_
from datetime import datetime, timedelta
from werkzeug import secure_filename
from flask_login import LoginManager


app = Flask(__name__)
login = LoginManager(app)
login.login_view = 'login'
app.secret_key = 'certificates-management'

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///certificates.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

dir_path = os.path.dirname(os.path.realpath(__file__))

db = SQLAlchemy(app)

from views import *

def month_string_to_number(string):
    m = {
            'jan': '1',
            'feb': '2',
            'mar': '3',
            'apr': '4',
            'may': '5',
            'jun': '6',
            'jul': '7',
            'aug': '8',
            'sep': '9',
            'oct': '10',
            'nov': '11',
            'dec': '12'
        }
    s = string.strip()[:3].lower()

    try:
        out = m[s]
        return out
    except:
        raise ValueError('Not a month')

if __name__ == '__main__':
    app.run(debug=True)

views.py

import sqlite3
import json
import os
import csv
import codecs
from flask import Flask, jsonify, g, request, abort, render_template, redirect, url_for, flash
from flask_sqlalchemy import Model, SQLAlchemy
from models import Worker, Certificates, Logs, User, return_workers, insert_db, create_log_entry
from sqlalchemy import text, and_
from datetime import datetime, timedelta
from werkzeug import secure_filename
from app import app, db, month_string_to_number
from flask_login import current_user, login_user, logout_user, login_required
from urlparse import urlparse

@app.errorhandler(404)
def not_found(error):
    return render_template('error.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        if current_user.is_authenticated:
            return redirect(url_for('index'))
        user_name = request.form['username']
        user_password = request.form['password']
        remember_me = request.form.get('remember_me', False)
        user = User.query.filter_by(username=user_name).first()
        dir(user)
        if user is None or not user.check_password(user_password):
            flash('Invalid username or password')
            return redirect(url_for('login'))
        login_user(user, remember=remember_me)
        create_log_entry(current_user.name, "Logged in to the system", "Login")
        flash("Login successfull", 'success')
        return redirect(url_for('index'))
    return render_template('login.html')

@app.route('/logout')
def logout():
    create_log_entry(current_user.name, "Logged out from the system", "Logout")
    logout_user()
    flash("Logged out successfully", 'success')
    return redirect(url_for('index'))

models.py

from app import app, db, login
import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=False)
    username = db.Column(db.String(255), nullable=False, unique=True)
    password_hash = db.Column(db.String(255), nullable=False)

    def __init__(self, username, password):
        self.username = username
        self.password_hash = password

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

WSGI代码是这样的:

import sys
sys.path.append("/var/www/certs-management")
from app import app as application

Apache配置:

<virtualhost *:80>
    ServerName myserver.example

    WSGIDaemonProcess certs-management user=apache group=apache threads=5 home=/var/www/certs-management/
    WSGIScriptAlias / /var/www/certs-management/cert-management.wsgi

    Alias /static /var/www/certs-management/static/
     <Directory "/var/www/certs-management/static/">
      Order allow,deny
      Allow from all
    </Directory>
    Alias /templates /var/www/certs-management/templates/
    <Directory "/var/www/certs-management/templates/">
      Order allow,deny
      Allow from all
    </Directory>
    <directory /var/www/certs-management>
        WSGIProcessGroup certs-management
        WSGIApplicationGroup %{GLOBAL}
        WSGIScriptReloading On
        Order deny,allow
        Allow from all
    </directory>
</virtualhost>

错误消息如下:

[Wed Jan 31 18:59:48.397516 2018] [mpm_prefork:notice] [pid 5634] AH00171: Graceful restart requested, doing restart
[Wed Jan 31 18:59:48.546219 2018] [auth_digest:notice] [pid 5634] AH01757: generating secret for digest authentication ...
[Wed Jan 31 18:59:48.546904 2018] [lbmethod_heartbeat:notice] [pid 5634] AH02282: No slotmem from mod_heartmonitor
[Wed Jan 31 18:59:48.547518 2018] [mpm_prefork:notice] [pid 5634] AH00163: Apache/2.4.6 (Red Hat Enterprise Linux) mod_wsgi/3.4 Python/2.7.5 configured -- resuming normal operations
[Wed Jan 31 18:59:48.547538 2018] [core:notice] [pid 5634] AH00094: Command line: '/usr/sbin/httpd'
[Wed Jan 31 18:59:52.011929 2018] [:error] [pid 3881] [remote :176] mod_wsgi (pid=3881): Target WSGI script '/var/www/certs-management/cert-management.wsgi' cannot be loaded as Python module.
[Wed Jan 31 18:59:52.011985 2018] [:error] [pid 3881] [remote :176] mod_wsgi (pid=3881): Exception occurred processing WSGI script '/var/www/certs-management/cert-management.wsgi'.
[Wed Jan 31 18:59:52.012015 2018] [:error] [pid 3881] [remote :176] Traceback (most recent call last):
[Wed Jan 31 18:59:52.012033 2018] [:error] [pid 3881] [remote :176]   File "/var/www/certs-management/cert-management.wsgi", line 3, in <module>
[Wed Jan 31 18:59:52.012098 2018] [:error] [pid 3881] [remote :176]     from app import app as application
[Wed Jan 31 18:59:52.012111 2018] [:error] [pid 3881] [remote :176]   File "/var/www/certs-management/app.py", line 26, in <module>
[Wed Jan 31 18:59:52.012158 2018] [:error] [pid 3881] [remote :176]     from views import *
[Wed Jan 31 18:59:52.012169 2018] [:error] [pid 3881] [remote :176]   File "/var/www/certs-management/views.py", line 12, in <module>
[Wed Jan 31 18:59:52.012320 2018] [:error] [pid 3881] [remote :176]     from app import app, db, month_string_to_number
[Wed Jan 31 18:59:52.012347 2018] [:error] [pid 3881] [remote :176] ImportError: cannot import name month_string_to_number

我真的不知道为什么会这样。 要配置此应用程序,我只需按照以下文档: http://flask.pocoo.org/docs/0.12/deploying/mod_wsgi/

PS:服务器名称不对,并且还删除了有关远程主机IP的信息 - 我确信这与此问题无关。

谢谢。

2 个答案:

答案 0 :(得分:1)

它看起来不像WSGI或Apache的问题,但事实上你有循环导入。在wagtaildocs,您要从app.py

导入所有内容
views.py

from views import * 中,您从views.py导回:

app.py

真正的问题是您使用from app import app, db, month_string_to_number 进行导入。如果您改为使用from ... import ...然后将对象称为import views,那么它应该有效。如果您对理解原因感兴趣,请参阅this response on Reddit

如果这样可以解决您的问题或是否还有其他问题,请告诉我们。

答案 1 :(得分:0)

在检查了Renato的建议之后,我做了一些不同的事情来解决这个问题。 事实上,循环导入是真正的问题,而不是WSGI,而不是Apache。

我没有从app.py调用views.py中的一个函数,而是将此函数month_string_to_number移至views.py,并将导入从app.py移至{ {1}}。

它解决了这个问题。

如果你遇到这样的问题,你应该检查你的循环导入,以确保你没有犯这个错误。