我只有一个大文件服务于我的应用程序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的信息 - 我确信这与此问题无关。
谢谢。
答案 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}}。
它解决了这个问题。
如果你遇到这样的问题,你应该检查你的循环导入,以确保你没有犯这个错误。