使用 WSGI 和 Apache 服务的 Flask 应用程序出现错误 500
Flask application served with WSGI and Apache getting Error 500
我的应用程序只有一个大文件 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 的信息也已删除 - 我确信这与问题无关。
谢谢。
这看起来不像是 WSGI 或 Apache 的问题,而是您有循环导入的事实。在您的 app.py
中,您正在从 views.py
:
导入所有内容
from views import *
并且在 views.py
中,您从 app.py
导入:
from app import app, db, month_string_to_number
真正的问题是您正在使用 from ... import ...
导入。如果您改为使用 import views
然后将对象引用为 views.xyz
,它应该可以工作。如果您有兴趣了解原因,请参阅 this response on Reddit。
如果这能解决您的问题或是否还有其他问题,请告诉我们。
在检查了 Renato 的建议后,我做了一些不同的事情来解决这个问题。
事实上,循环导入才是真正的问题,不是 WSGI,也不是 Apache。
我没有从 views.py
调用 app.py
中的一个函数,而是将此函数 month_string_to_number
移至 views.py
并删除了从 app.py
的导入进入 views.py
.
问题解决了。
如果您遇到任何此类问题,您应该检查您的循环导入以确保您没有犯这个错误。
我的应用程序只有一个大文件 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 的信息也已删除 - 我确信这与问题无关。
谢谢。
这看起来不像是 WSGI 或 Apache 的问题,而是您有循环导入的事实。在您的 app.py
中,您正在从 views.py
:
from views import *
并且在 views.py
中,您从 app.py
导入:
from app import app, db, month_string_to_number
真正的问题是您正在使用 from ... import ...
导入。如果您改为使用 import views
然后将对象引用为 views.xyz
,它应该可以工作。如果您有兴趣了解原因,请参阅 this response on Reddit。
如果这能解决您的问题或是否还有其他问题,请告诉我们。
在检查了 Renato 的建议后,我做了一些不同的事情来解决这个问题。 事实上,循环导入才是真正的问题,不是 WSGI,也不是 Apache。
我没有从 views.py
调用 app.py
中的一个函数,而是将此函数 month_string_to_number
移至 views.py
并删除了从 app.py
的导入进入 views.py
.
问题解决了。
如果您遇到任何此类问题,您应该检查您的循环导入以确保您没有犯这个错误。